vue中this.$message的實(shí)現(xiàn)過程詳解
一、vue中為什么可以直接使用this.$message
1、Message在開發(fā)中的使用頻率很高,也算是Element-UI組件庫中比較簡單的,對于感興趣的朋友可以一起探討一下Message組件的實(shí)現(xiàn)
2、組件的使用
this.$message('這是一條消息提示');
this.$message({ message: '恭喜你,這是一條成功消息', type: 'success' });3、整體的執(zhí)行過程
Vue項目中的使用如下:
// main.js // 1.引入組件庫 import ElementUI from 'element-ui'; // 2.使用組件庫 Vue.use(ElementUI);
Element-UI組件庫中邏輯如下:
每次當(dāng)Vue.use的時候,在Element—UI內(nèi)部會觸發(fā)Element-UI的install方法,然后將組件注冊為全局組件,將方法放到Vue.prototype上,本次只看Message部分即可
// 文件目錄:node-modules/element-ui/src/index.js
// 1.引入Message對象
import Message from '../packages/message/index.js';
// 2. 定義 install函數(shù),
const install = function(Vue, opts = {}) {
// 將組件遍歷注冊為全局組件,例如Button組件
components.forEach(component => {
Vue.component(component.name, component);
});
// 將方法放到Vue原型上
Vue.prototype.$message = Message;
};
經(jīng)過上述兩步的處理,我們可以直接在項目中通過this.$message進(jìn)行組件的展示控制,接下來繼續(xù)探索Element-UI內(nèi)部如何處理的。
二、message組件的內(nèi)部實(shí)現(xiàn)原理
1、設(shè)計思路
Message的調(diào)用方式都是通過this.$message進(jìn)行調(diào)用,通過傳遞不同的options進(jìn)行組件樣式和內(nèi)容的控制,展示的html是動態(tài)的插入到document中并在duration之后移除,組件的展示通過vue實(shí)例訪問并控制。
組件的整體結(jié)構(gòu)分為展示部分和控制部分
展示部分(main.vue):單獨(dú)抽離出一個組件,將組件的展示邏輯和交互封裝集中處理
控制部分(main.js):是承接vue實(shí)例和組件展示

2、展示部分,即main.vue
首先看一下刪減版本之后展示部分的組件內(nèi)容,代碼刪除了容錯和邊界值判斷的代碼,僅僅展示了基本功能。
<template>
<transition name="el-message-fade" @after-leave="handleAfterLeave">
<div
class="el-message"
:style="positionStyle"
v-show="visible">
<slot>
<p>{{ message }}</p>
</slot>
</div>
</transition>
</template>
<script type="text/javascript">
export default {
data() {
return {
visible: false,
message: '',
duration: 3000,
onClose: null,
closed: false,
verticalOffset: 20,
timer: null
};
},
computed: {
positionStyle() { // 控制當(dāng)前組件的顯示位置
return {
'top': `${ this.verticalOffset }px`
};
}
},
watch: {
// 監(jiān)聽closed的變化,設(shè)置為true時,將組件銷毀
closed(newVal) {
if (newVal) {
this.visible = false;
}
}
},
methods: {
// transtion組件的鉤子,觸發(fā)after-leave時執(zhí)行
handleAfterLeave() {
this.$destroy(true); // 銷毀組件
this.$el.parentNode.removeChild(this.$el); // 將組件的DOM移除
},
close() {
this.closed = true; // 組件隱藏
if (typeof this.onClose === 'function') {
this.onClose(this);
}
},
// 每次手動啟動編譯之后 設(shè)置其展示時間duration之后關(guān)閉
startTimer() {
if (this.duration > 0) {
this.timer = setTimeout(() => {
if (!this.closed) {
this.close();
}
}, this.duration);
}
}
},
mounted() {
this.startTimer();
}
};
</script>使用了Vue官方封裝的transition組件,不僅提供了良好的過渡效果,還提供了合適的鉤子便于開發(fā)者控制,組件中使用after-leave鉤子,當(dāng)組件銷毀時進(jìn)行組件的銷毀和DOM的移除,visible用于控制組件的展示與銷毀,計算屬性positionStyle用于設(shè)置組件的展示位置,message為組件展示的內(nèi)容數(shù)據(jù),搞明白這些變量、計算屬性和方法的作用即可。
script部分可參考注釋進(jìn)行理解,需要注意兩個地方
(1)首先需要注意生命周期鉤子mount時做的事情,為何如此做?因為不存在el選項,實(shí)例不會立即進(jìn)入編譯階段,需要顯示調(diào)用$mount 手動開啟編譯
(2)還需要注意的時close函數(shù)中做了兩件事,設(shè)置closed的值觸發(fā)對應(yīng)的watch,關(guān)閉組件,若是存在onClose方法則調(diào)用,注意這個onClose函數(shù)的定義是在控制部分定義,稍后會說明
3、控制部分 至此已經(jīng)清楚Vue中是通過this.$message觸發(fā)組件的展示,而展示部分的組件內(nèi)容也已完成,現(xiàn)在就需要通過控制部分將兩者連接,達(dá)到期望的功能
與Vue關(guān)聯(lián)比較簡單,僅僅是定義一個方法并將其導(dǎo)出即可
const Message = options => {
// 邏輯編寫....
}
export default Message;這個時候通過this.$message即可調(diào)用,接下來便是將Message函數(shù)與組件關(guān)聯(lián),并控制展示部分
Message核心需要做那些事情
- 編譯組件,使用渲染并插入到
body中 - 控制組件內(nèi)的
visible變量,觸發(fā)組件的展示 - 控制組件內(nèi)的
verticalOffset變量,決定組件展示時的位置
手動開啟組件編譯,獲取其實(shí)例訪問內(nèi)部data和渲染到頁面上
// 1. 使用基礎(chǔ) Vue 構(gòu)造器,創(chuàng)建一個“子類”
let MessageConstructor = Vue.extend(Main);
// 2. 組件實(shí)例, 可以通過instance訪問 visible和verticalOffset
instance = new MessageConstructor({
data: options
});整個Message方法其余部分就是在做容錯和健壯處理,整體簡潔版代碼如下
let MessageConstructor = Vue.extend(Main);
let instance; // 當(dāng)前組件
let instances = []; // 將所有的message組件收集,用于位置的判斷和銷毀等
let seed = 1; // 每個message實(shí)例都有一個唯一標(biāo)識
const Message = options => {
options = options || {
message: 'content' + Date.now(),
onClose(message){
console.log('關(guān)閉時的回調(diào)函數(shù), 參數(shù)為被關(guān)閉的 message 實(shí)例',message);
}
};
if (typeof options === 'string') {
options = {
message: options
};
}
// 關(guān)閉時的回調(diào)函數(shù), 參數(shù)為被關(guān)閉的 message 實(shí)例
let userOnClose = options.onClose;
let id = 'message_' + seed++;
// 增加 onClose 方法,組件銷毀時,在組件內(nèi)部調(diào)用
options.onClose = function() {
Message.close(id, userOnClose);
};
// 組件實(shí)例,此時options與組件的data關(guān)聯(lián)
instance = new MessageConstructor({
data: options
});
instance.id = id; // 設(shè)置ID
instance.$mount(); // 因為不存在el選項,實(shí)例不會立即進(jìn)入編譯階段,需要顯示調(diào)用$mount 手動開啟編譯
document.body.appendChild(instance.$el); // 將Message 組件插入到body中
// 設(shè)置組件距離頂部的距離,每個message組件會有16px的間距
let verticalOffset = options.offset || 20;
instances.forEach(item => {
verticalOffset += item.$el.offsetHeight + 16;
});
instance.verticalOffset = verticalOffset;
instance.visible = true; // 控制展示
instance.$el.style.zIndex = 99; // 控制層級
instances.push(instance);
return instance;
};
this.$message.error('')的實(shí)現(xiàn)
Message組件支持this.$message.error('錯了哦,這是一條錯誤消息');調(diào)用使用,到目前為止還不支持,代碼比較簡單直接上代碼
// 為每個 type 定義了各自的方法,如 Message.success(options),可以直接調(diào)用
['success', 'warning', 'info', 'error'].forEach(type => {
Message[type] = options => {
if (typeof options === 'string') {
options = {
message: options
};
}
options.type = type;
return Message(options);
};
});
展示組件內(nèi)部會調(diào)用this.onClose(this),組件內(nèi)部設(shè)置this.visible=false關(guān)閉彈框,并且移除其對應(yīng)的DOM結(jié)構(gòu),但是頁面展示多個組件時需要修改其余組件的位置
onClose函數(shù)是在Message函數(shù)中定義
// 關(guān)閉時的回調(diào)函數(shù), 參數(shù)為被關(guān)閉的 message 實(shí)例
let userOnClose = options.onClose;
// 增加 onClose 方法,組件銷毀時,在組件內(nèi)部調(diào)用
options.onClose = function() {
Message.close(id, userOnClose);
};onClose函數(shù)最終調(diào)用的是Message上的靜態(tài)方法close
函數(shù)Message.close內(nèi)部主要做了幾件事情
- 在頁面顯示的組件數(shù)組中找到需要關(guān)閉的組件,將其移除
- 重新計算剩余組件的位置
三、總結(jié)
至此基礎(chǔ)版本的Message已經(jīng)完成,組件的代碼不到200行,通過源碼的簡單閱讀和分析,知識點(diǎn)并不是很多,但是優(yōu)秀組件封裝的思路還是值得學(xué)習(xí)和借鑒
到此這篇關(guān)于vue中this.$message的實(shí)現(xiàn)過程詳解的文章就介紹到這了,更多相關(guān)vue中this.$message實(shí)現(xiàn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue2使用wangeditor實(shí)現(xiàn)數(shù)學(xué)公式和富文本編輯器
這篇文章主要為大家詳細(xì)介紹了vue2如何使用wangeditor實(shí)現(xiàn)數(shù)學(xué)公式和富文本編輯器功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以了解一下2023-12-12
vue3父子同信的雙向數(shù)據(jù)的項目實(shí)現(xiàn)
我們知道的是,父傳子的通信,和子傳父的通信,那如何實(shí)現(xiàn)父子相互通信的呢,本文就來詳細(xì)的介紹一下,感興趣的可以了解一下2023-08-08
解決vue組件沒顯示,沒起作用,沒報錯,但該顯示的組件沒顯示問題
這篇文章主要介紹了解決vue組件沒顯示,沒起作用,沒報錯,但該顯示的組件沒顯示問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-09-09
Vue監(jiān)聽Enter鍵的方法總結(jié)與區(qū)別
這篇文章主要給大家介紹了關(guān)于Vue監(jiān)聽Enter鍵的方法與區(qū)別的相關(guān)資料,在Vue中我們可以通過監(jiān)聽鍵盤事件來實(shí)現(xiàn)回車鍵切換焦點(diǎn)的功能,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-10-10

