elementui原始碼學習之仿寫一個el-message
問題描述
工作中雖然使用工具庫很快樂很高效,但我們還是要抽空看看工具庫的原始碼,因為原始碼中會用到一些不經常使用的api方法,記住這些api方法,可提升自己的程式設計能力,有助於以後封裝自己的工具庫,從而更好的實現一些需求。
需求分析
元件封裝之前,我們要想一下要封裝的這個元件的應用場景和使用需求有哪些,以此為突破口,便於更好的實現程式碼邏輯
應用場景和需求:訊息提示
愚以為,message主要是資訊提示,應用場景在於使用者執行了一些操作,是否成功或失敗之類的互動反饋。所以,我們可以定義這個要封裝的元件有以下需求:
- 需要可以輸入資訊文字 message引數
- 需要message資訊的型別反饋(成功反饋、警告反饋、錯誤反饋、普通訊息反饋)type引數
- 需要提示完以後,可以設定預設消失時間 duration引數
- 當滑鼠懸浮的時候保留這個訊息提示,不讓其消失 定時器timer引數
- 其他諸如 提示小圖示的型別和文字是否居中 之類的
如果我們看餓了麼UI官方的元件,我們會發現官方考慮的還是十分詳細的,給到了很多配置項Options引數,不過在我們自己實際封裝元件中,不需要像官方那樣,做很多的配置項,只需要實現常用的配置項即可,保留最實用的功能即可。
餓了麼UI官方el-message元件:https://element.eleme.cn/#/zh-CN/component/message
效果圖
理解方式
關於這個功能效果,個人建議可以如下理解 - 先複習一下平常用的不多的api - 再把程式碼clone下來,跑起來(文末附上github程式碼倉庫地址) - 結合註釋,既可快速理解了
知識點複習之:class的陣列用法和:style用法
``js
// html
<div
:class="[
'messageBox', /* .messageBox這個類名確定要加到div這個標籤上 */
center ? 'horizontal' : '', /* 是否給div標籤加上.horizontal這個類名取決於center這個變數的值是否為true */
typeArr.includes(type) ? type : '', /* 是否給div這個標籤加上type變數值的類名,取決於typeArr變數陣列是否包含type的值 */
]"
:style="controlTop" /* 等價於:style={top:
12px`} 等價於 style="top: 12px" 即距離頂部top值為12畫素 */
// js
data() {
return {
center: false, // 是否讓水平文字居中,預設false
type: "info", // 預設info型別
typeArr: ["info", "success", "warning", "error"], // 總共4種類型
};
},
computed: {
controlTop() {
return { top: 12px
};
},
},
```
為什麼要提到:class的陣列用法以及:style的用法呢?
因為在本例中,給message繫結四種類型(成功、警告、錯誤、資訊)的樣式,就需要使用到;
使用者多次點選觸發message的出現,控制下一個message的位置在上一個的下方,就需要讓不斷的更改下一個message的top值;
知識點複習之transition過渡鉤子函式
```js // html <transition v-on:before-enter="beforeEnter" / 過渡出現進入之前 / v-on:enter="enter" / 過渡出現進入 / v-on:after-enter="afterEnter" / 過渡出現進入之後 / v-on:enter-cancelled="enterCancelled" / 取消進入過渡 / v-on:before-leave="beforeLeave" / 過渡消失離開之前 / v-on:leave="leave" / 過渡消失離開 / v-on:after-leave="afterLeave" / 過渡消失離開之後 / v-on:leave-cancelled="leaveCancelled" / 取消過渡消失離開 /
<!-- ... -->
// js methods: { // ... afterLeave(){ / 本例中使用了這個鉤子,當過渡消失的時候會觸發這個鉤子函式, 我們可以在鉤子函式中寫一些js邏輯程式碼,進行相應操作 / } // ...
} ``` 那麼,什麼時候,過渡消失,什麼時候過渡出現?
最明顯的就是,v-show由true改為false、由false改為true的時候,會自動觸發transition的過渡鉤子函式執行
本例中使用過渡鉤子函式主要是因為,當消失一個message的時候,需要減少一個message的計數,所以需要通過這個鉤子去進行js邏輯程式碼曹組歐
過渡鉤子詳見官方文件:https://cn.vuejs.org/v2/guide/transitions.html
知識點複習之vue銷燬元件的方式
- 使用
v-if
官方推薦最好的方式 - 使用key 一般用的不是特別多
this.$destroy(true)
vue的1.x版本常常使用,從2.x版本就不支援了,相當於相容寫法- 自己手動移除
this.$el.parentNode.removeChild(this.$el);
本例使用之 關於第3點和第4點,尤大佬還親自回答了關於這個問題的issues。簡單截圖如下:
issues地址如下:https://github.com/vuejs/vue/issues/3534
為什麼提到這個銷燬dom方式呢?
因為我們使用v-show加上去transition控制message的隱藏和消失的,這個效果絲滑一些,沒有使用v-if直接幹掉dom。所以需要手動寫程式碼,在過渡消失以後,當我們看不到message的時候,再偷偷的給message移除掉即可
完整程式碼
整體程式碼思路
- 搞一個message元件用於繼承
- 使用Vue.extend繼承這個元件形成一個構造器
- 定義一個函式,函式一執行,就使用構造器建立一個message顯示,預設3秒自動消失
- 把這個函式掛載在原型上,並暴露出去,方便訪問使用
關於Vue.extend繼承不太熟悉的,可以先看看筆者的另外兩篇文章哦
繼承... https://juejin.cn/post/7021724333391216677
繼承... https://juejin.cn/post/7108542695387168799
使用的.vue檔案程式碼
```js // html
// 一種是原型鏈使用方式,另一種是引入使用方式 import MyMessage from "@/components/index.js"; methods: { showMessage1() { this.$myMessage({ message: "資訊彈出", type: "info", }); }, showMessage2() { this.$myMessage({ message: "成功彈出", type: "success", }); }, showMessage3() { this.$myMessage({ message: "警告彈出", type: "warning", }); }, showMessage4() { this.$myMessage({ message: "錯誤彈出", type: "error", }); }, showMessage5() { this.$myMessage({ message: "彈出5秒關閉", }); }, showMessage6() { this.$myMessage({ message: "文字居中哦", center: true, }); }, showMessage7() { MyMessage({ message: "引入使用", type: "success", }); }, }, ```
通過繼承掛載原型上便於動態建立檔案程式碼
```js import Vue from 'vue'; import messageComponent from './src/index.vue' // 引入元件,方便繼承 let MessageConstructor = Vue.extend(messageComponent); // 引入一個message構造器,方便new之
let instance = null // 定義元件例項 let count = 0 // 定義統計次數,便於知道建立多少個例項
const MyMessage = function (options) { if (options.duration & typeof options.duration !== 'number') { // 對於duration數字型別的校驗 console.error('Error! duration Must be a numeric type ') // 使用者亂傳遞非數字型別引數,就拋錯不執行後續程式碼 return } count = count + 1 // MyMessage函式呼叫一次,統計次數加一個 instance = new MessageConstructor({ // 例項化一個元件例項 data: options, // data傳引數,元件的data接收(即傳遞配置項) propsData: { // propsData傳參, count: count, // 將統計的次數傳遞給子元件 cutCount: cutCount // 傳遞一個函式,當MyMessage消失的時候,通知外界 }, }); instance.$mount(); // 例項元件掛載 document.body.appendChild(instance.$el); // 把這個元件例項的dom元素,追加到document文件中 instance.isShowMyMessage = true; // 將元件的isShowMyMessage屬性值置為true,即讓例項出現,即訊息出現 return instance; // MyMessage函式執行一次,就會返回一個加工好的例項物件 }
function cutCount() { // 當message消失一個 count = count - 1 // 就把外界統計的數量減少一個 let messageBoxDomList = document.querySelectorAll('.messageBox') // 然後選中所有的messageDOM元素 for (let i = 0; i < messageBoxDomList.length; i++) { // 遍歷一下這個DOM偽陣列 let dom = messageBoxDomList[i] // 所有的都往上移動60畫素 dom.style['top'] = parseInt(dom.style['top']) - 60 + 'px' } }
export default MyMessage // 暴露出去 Vue.prototype.$myMessage = MyMessage; // 掛載在vue原型上,方便this.$myMessage呼叫 ```
用於繼承的message元件程式碼
```js
```
github倉庫程式碼地址
elementui原始碼學習仿寫元件,準備工作不忙的時候,寫一個系列,我會盡可能多寫點註釋哦。與大家共同進步成長^_^
github地址:https://github.com/shuirongshuifu/elementSrcCodeStudy
- 什麼?後端要一次性返回我10萬條資料!且看我這8種方案機智應對!
- 效能優化之通俗易懂學習requestAnimationFrame和使用場景舉例
- 23個css動畫效果,持續更新中...
- elementui原始碼學習之仿寫一個el-message
- 專案優化之使用compression-webpack-plugin外掛開啟gzip壓縮,以vue為例
- 巧妙使用Vue.extend繼承元件實現el-table雙擊可編輯(不使用v-if和v-else)
- 通俗易懂講解並手寫一個vue資料雙向繫結案例
- vue中使用docx-preview外掛預覽word文件(後端express)
- react元件通訊方式之~圖解父子元件通訊和兄弟元件通訊pubsub-js
- 解決react警告:findDOMNode is deprecated in StrictMode. findDOMNode was passed an...
- vue自定義指令使用~以仿寫v-show和實現v-copy為例講解
- el-table表頭文字換行的三種方式
- elementUI時間日期選擇器更改小圖示的位置和icon
- 兩種方式解決頁面重新整理vuex中資料丟失問題(詳細講解)
- vue元件的遞迴自呼叫~程式碼思路分析
- el-tree樹元件的懶載入寫法步驟