自定義全局組件

經(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++);
  //把用戶傳進來的options展開,和id進行合并
  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ù)給一個默認值
    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)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蜒滩,隨后出現(xiàn)的幾起案子滨达,更是在濱河造成了極大的恐慌,老刑警劉巖俯艰,帶你破解...
    沈念sama閱讀 206,602評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件捡遍,死亡現(xiàn)場離奇詭異,居然都是意外死亡竹握,警方通過查閱死者的電腦和手機画株,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來啦辐,“玉大人谓传,你說我怎么就攤上這事∏酃兀” “怎么了续挟?”我有些...
    開封第一講書人閱讀 152,878評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長侥衬。 經(jīng)常有香客問我诗祸,道長,這世上最難降的妖魔是什么轴总? 我笑而不...
    開封第一講書人閱讀 55,306評論 1 279
  • 正文 為了忘掉前任贬媒,我火速辦了婚禮,結(jié)果婚禮上肘习,老公的妹妹穿的比我還像新娘际乘。我一直安慰自己,他們只是感情好漂佩,可當(dāng)我...
    茶點故事閱讀 64,330評論 5 373
  • 文/花漫 我一把揭開白布脖含。 她就那樣靜靜地躺著,像睡著了一般投蝉。 火紅的嫁衣襯著肌膚如雪养葵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,071評論 1 285
  • 那天瘩缆,我揣著相機與錄音关拒,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛着绊,可吹牛的內(nèi)容都是我干的谐算。 我是一名探鬼主播,決...
    沈念sama閱讀 38,382評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼归露,長吁一口氣:“原來是場噩夢啊……” “哼洲脂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剧包,我...
    開封第一講書人閱讀 37,006評論 0 259
  • 序言:老撾萬榮一對情侶失蹤恐锦,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后疆液,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體一铅,經(jīng)...
    沈念sama閱讀 43,512評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,965評論 2 325
  • 正文 我和宋清朗相戀三年堕油,在試婚紗的時候發(fā)現(xiàn)自己被綠了馅闽。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,094評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡馍迄,死狀恐怖福也,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情攀圈,我是刑警寧澤于宙,帶...
    沈念sama閱讀 33,732評論 4 323
  • 正文 年R本政府宣布臭墨,位于F島的核電站软吐,受9級特大地震影響呛梆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜犬辰,卻給世界環(huán)境...
    茶點故事閱讀 39,283評論 3 307
  • 文/蒙蒙 一嗦篱、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧幌缝,春花似錦灸促、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至轿偎,卻和暖如春典鸡,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背坏晦。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評論 1 262
  • 我被黑心中介騙來泰國打工萝玷, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留嫁乘,地道東北人。 一個月前我還...
    沈念sama閱讀 45,536評論 2 354
  • 正文 我出身青樓球碉,卻偏偏與公主長得像蜓斧,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子汁尺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,828評論 2 345

推薦閱讀更多精彩內(nèi)容

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