vue的全局API : vue.extend(component)

vue.extend(component)

vue.extend我們在開發中較少用到,相比於vue.component,它的使用會比較複雜些。但是在一些獨立組件開發中,比如彈框組件,需要掛載到body中,而不是#app中,這時就需要用到vue.extend+$mount了。

 

vue.extend()的官方定義:

vue.extend(options)

  • 參數:{object} options
  • 用法:

    使用基礎 Vue 構造器,創建一個“子類”。參數是一個包含組件選項的對象。

    data 選項是特例,需要注意 - 在 Vue.extend() 中它必須是函數

    <div id="mount-point"></div>
    // 創建構造器
    var Profile = Vue.extend({
      template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
      data: function () {
        return {
          firstName: 'Walter',
          lastName: 'White',
          alias: 'Heisenberg'
        }
      }
    })
    // 創建 Profile 實例,並掛載到一個元素上。
    new Profile().$mount('#mount-point')

    結果如下:

    <p>Walter White aka Heisenberg</p>

    注:可以看到vue.extend創建的是Vue構造器,而不是我們平時寫的組件實例,所以不可以通過new Vue({ components: testExtend })  來直接使用,需要用new Profile().$mount('#mount-point')來掛載到#mount-point'元素上。

爲什麼使用extend

在vue項目中,有了初始化的根實例後,所有頁面基本上都是通過router來管理,組件也是通過import來進行局部註冊,所以組件的創建我們不需要去關注,相比extend來更簡單一點。但是會有如下幾個缺點:

  1. 組件模板都是事先定義好的,如果我要從接口動態渲染組件怎麼辦?
  2. 所有內容都是在#app下渲染,註冊組件都是在當前位置下渲染,如果我們要實現一個類似於window.alert()組件,要求像調用js函數一樣調用它怎麼辦?

所以這時候就需要用到extend。它可以實現在body上掛載組件,使用document.body.appendChild(Profile.$el)。

下面的例子是用extend和render兩種方式創建的彈框提示組件:

Notice.vue組件:

<template>
  <div class="box" v-if="isShow">
    <h3>{{title}}</h3>
    <p class="box-content">{{message}}</p>
  </div>
</template>

<script>
export default {
  props: {
    title: {
      type: String,
      default: ""
    },
    message: {
      type: String,
      default: ""
    },
    duration: {
      type: Number,
      default: 2000
    }
  },
  data() {
    return {
      isShow: false
    };
  },
  methods: {
    show() {
      this.isShow = true;
      setTimeout(this.hide, this.duration);
    },
    hide() {
      this.isShow = false;
      this.remove();
    }
  }
};
</script>

<style>
.box {
  position: fixed;
  width: 100%;
  top: 16px;
  left: 0;
  text-align: center;
  pointer-events: none;
  background-color: #fff;
  border: grey 3px solid;
  box-sizing: border-box;
}
.box-content {
  width: 200px;
  margin: 10px auto;
  font-size: 14px;
  padding: 8px 16px;
  background: #fff;
  border-radius: 3px;
  margin-bottom: 8px;
}
</style>

 

src/utils/create.js

import Vue from 'vue';
// import Notice from '@/components/Notice.vue';

//create方法最終的目標是把組件實例返回
function create(component, props) {
  //組件構造函數如何獲取?
  //1、Vue.extend()

  const Ctor = Vue.extend(component)
  //創建組件實例
  const comp = new Ctor({ propsData: props })
  comp.$mount()
  document.body.appendChild(comp.$el)
  comp.remove = function () {
    document.body.removeChild(comp.$el)
    comp.$destroy()
  }




  /* //2、render
  const vm = new Vue({
    //h是createElement,返回的是vNode,是虛擬dom,需要掛載才能變成真實dom
    render: h => h(component, { props })
  }).$mount() //不指定宿主元素,則會創建真實dom,但是不會做追加dom操作,切記這裏不能把body作爲宿主元素

  //vm.$el是獲取真實dom,把真實dom放到body中
  document.body.appendChild(vm.$el)
  const comp = vm.$children[0]

  //刪除彈框組件,不能一直往body中追加彈框,這樣程序會崩
  comp.remove = function () {
    document.body.removeChild(vm.$el)
    vm.$destroy()
  } */
  return comp

}
// export default create
export default {
  install(Vue) {
    Vue.prototype.$notice = function (options) {

      return create(Notice, options)
    }
  }
}

main.js中註冊成全局組件

import create from './utils/create';
// Vue.prototype.$create = create
Vue.use(create)    //create已經是組件對象了,進行全局註冊

在頁面中調用彈框提示組件:index.vue

import Notice from "@/components/Notice.vue";


login() {
      this.$refs["kLoginForm"].validate(valid => {
        /* const notice = this.$create(Notice, {
          title: "社會你楊哥喊你來搬磚",
          message: valid ? "請求登錄!" : "校驗失敗!",
          duration: 3000
        });
        notice.show(); */

        //這種用法更好,因爲不用再在用的時候引和Notice組件了,create.js中已經有了,利用install
        console.log("this.$notice():===", this.$notice());
        const notice = this.$notice({
          title: "社會你楊哥喊你來搬磚",
          message: valid ? "請求登錄!" : "校驗失敗!",
          duration: 2000
        });
        notice.show();

        
      });
    }

 

至此,一個全局的彈框組件就寫好了。

總結:

1、component中寫一個Notice.vue的組件的dom結構。src/component/Notice.vue

2、把Notice寫成一個全局的工具函數,返回一個組件,並掛載到body上。src/utils/create.js

3、在main.js中註冊成全局組件。

4、在頁面中使用這個全局彈框組件。index.vue

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章