自定義全局組件

經(jīng)常的,業(yè)務(wù)中需要用到一些全局的組件,類似Toast、彈窗等,如果我們在每個頁面都單獨的去引入的話,就會比較麻煩,那么,如何將組件作為全局組件調(diào)用呢?這樣的好處是在每個頁面調(diào)用的時候,不需要引入,直接調(diào)用,并將它掛載在body元素中,不會對我們的頁面樣式造成影響。

下面我們來看看如何自定義一個全局組件。
以一個Toast舉例
在components文件夾里,創(chuàng)建一個Notice.vue。

<template>
  <div class="alert">
    <div class="alert-container" v-for="item in alerts" :key="item.id">
      <div class="alert-content">{{item.content}}</div>
    </div>
  </div>
</template>

因為需要用到alerts,所以創(chuàng)建一個alerts數(shù)組。
在create()里,需要做一個id的自增控制。

name:'notice',
 data() {
       return {
                alerts: []
      }
},
created () {
       // id自增控制
       this.id = 0;
 }

代表來一條alert,就把id置為0,然后自增一下。
然后在里面添加2個方法,add()和del()。
add用來創(chuàng)建一個新的alert。

add(options) {
   //id放在this里,所以不是響應(yīng)式的
  const id = 'id_'+(this.id++);
  //把用戶傳進(jìn)來的options展開,和id進(jìn)行合并
  const _alert = { ...options, id: id };
  this.alerts.push(_alert);
  // 自動關(guān)閉
  const duration = options.duration || 1; //單位秒
  setTimeout(() => {
    this.del(id)
  },duration*1000);
},
del(id) {
     for(let i = 0;i < this.alerts.length; i++) {
          const element = this.alerts[i];
          if(element.id === id) {
               this.alerts.splice(i,1);
               break;
         }
     }
}

完善一下樣式

<style scoped lang="stylus">
.alert {
  position: fixed;
  width: 100%;
  top: 30px;
  left: 0;
  text-align: center;

  .alert-content {
    display: inline-block;
    padding: 8px;
    background: #fff;
    margin-bottom: 10px;
  }
}
</style>

寫完組件之后,如何全局的調(diào)用它?

  1. 最快的方式就是,直接使用別人寫好的api,比如cube-ui里的createAPI。
    在main.js里引入createAPI
import { createAPI } from 'cube-ui';
import Notice from './components/Notice.vue';
//創(chuàng)建$createNotice
createAPI(Vue,Notice,true); //參數(shù)3表示單例模式

然后在需要調(diào)用Notice的地方,比如Home.vue里

const notice = this.$createNotice();  //表示創(chuàng)建了一個notice實例,掛載在body上
notice.add({content:'lalala',duration:2})  //調(diào)用add方法
  1. 我們自定義一個服務(wù),全局調(diào)用Notice
    先創(chuàng)建一個services文件夾,創(chuàng)建一個notice.js
import Notice from '@/components/Notice.vue';
import Vue from 'vue';

// 給Notice添加一個創(chuàng)建組件實例的方法,可以動態(tài)編譯自身模板并掛載
Notice.getInstance = props => {
    // 創(chuàng)建一個Vue實例
    const instance = new Vue({
        // 渲染函數(shù): 用于渲染指定模板為虛擬DOM  
        // h是一個渲染函數(shù),可以把我們傳入的模板編譯成虛擬DOM
        render(h){ 
            // <Notice foo="bar"></Notice>
            return h(Notice, {props})
        }
    }).$mount(); // 執(zhí)行掛載
    
    // $mount() 是outerHTML,所以$mount('body')是不可以的,會替換body。
    // 所以不指定選擇器,則模板將被渲染為文檔之外的元素

    // 必須使用原生的dom api把它插入文檔中 
    // $el是渲染的Notice中真正的dom元素
    document.body.appendChild(instance.$el);

    // 獲取Notice實例   instance是vue實例,instance.$children取出實例下的虛擬DOM元素
    // $children指的是當(dāng)前Vue實例中包含的所有組件實例 $children[0]就是根,即是Notice實例
    const notice = instance.$children[0];
    return notice;
}

接下來設(shè)計一個單例模式,在全局范圍唯一的創(chuàng)建一個Notice實例,保證它的唯一性

let msgInstance = null;
function getInstance() {
    msgInstance = msgInstance || Notice.getInstance();
    return msgInstance;
}

暴露接口

export default {
    // info方法,參數(shù)給一個默認(rèn)值
    info({duration=2,content=''}){
        getInstance().add({
            content,duration
        });
    }
}

在創(chuàng)建完這個notice.js后,需要去main.js注冊

import notice from '@/services/notice';

Vue.prototype.$notice = notice;

最后去Home.vue里使用$notice。

this.$notice.info({
        duration: 3,
        content: '一些消息內(nèi)容'
})

這樣就實現(xiàn)了自定義全局組件,并調(diào)用

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 今天解決了一個長期困擾著我的問題,現(xiàn)在記錄一下,供日后參考。 涉及知識點是Vue.js官網(wǎng)教程中的插件使用 首先我...
    小羅程序員閱讀 934評論 1 3
  • 有時候我們在做開發(fā)的時候,就想自己寫一個插件然后就可以使用自己的插件,那種成就感很強。博主最近研究element-...
    前小白閱讀 781評論 0 0
  • 自定義全局組件 如果想自己創(chuàng)建新的組件,應(yīng)用在全局步驟 步驟一 步驟二 創(chuàng)建一個template組價 步驟三 創(chuàng)建...
    Amy_yqh閱讀 185評論 0 1
  • 在用vue構(gòu)建項目的過程中,我們有時會用到別人開發(fā)的組件如vue-router;使用他人組件的正常步驟如下:1、命...
    早起的鳥兒閱讀 446評論 0 0
  • 自定義vue全局組件 項目源碼: https://github.com/yanghanbin-sz/custom-...
    yanghanbin_it閱讀 631評論 0 0

友情鏈接更多精彩內(nèi)容