摘要:之前的項目一直在使用框架,中的組件使用時不需要在寫標簽,而是使用調(diào)用。這樣在組件中就可以通過的形式來使用了參考參考了的代碼封裝組件的一些技巧
之前的項目一直在使用Element-UI框架,element中的Notification、Message組件使用時不需要在html寫標簽,而是使用js調(diào)用。那時就很疑惑,為什么element ui使用this.$notify、this.$message就可以實現(xiàn)這樣的功能?1、實現(xiàn)消息彈窗組件的幾個問題
如何在任何組件中使用this.$message就可以顯示消息?
如何將消息的dom節(jié)點插入到body中?
同時出現(xiàn)多個消息彈窗時,消息彈窗的z-index如何控制?
2、效果預覽 3、代碼實現(xiàn)PMessage.vue
p-message.js
import Vue from "vue"; import PMessage from "./PMessage.vue"; import {popupManager} from "../../common/js/popup-manager"; let PMessageControl = Vue.extend(PMessage); let count = 0; // 存儲message組件實例,如需有關(guān)閉所有message的功能就需要將每個message組件都存儲起來 let instances = []; const isVNode = function (node) { return node !== null && typeof node === "object" && Object.prototype.hasOwnProperty.call(node, "componentOptions"); }; const Message = function (options) { options = options || {}; if(typeof options === "string"){ options = { message: options }; } let id = "message_" + ++count; let userOnClose = options.onClose; // PMsesage.vue銷毀時會調(diào)用傳遞進去的onClose,而onClose的處理就是將指定id的message組件從instances中移除 options.onClose = function (){ Message._close(id, userOnClose); }; /* 這里傳遞給PMessageControl的data不會覆蓋PMessage.vue中原有的data,而是與PMessage.vue中原有的data進行合并,類似 * 與mixin,包括傳遞methods、生命周期函數(shù)也是一樣 */ let instance = new PMessageControl({ data: options }); // 傳遞vNode if(isVNode(instance.message)){ instance.$slots.default = [instance.message]; instance.message = null; } instance.id = id; // 渲染元素,隨后使用原生appendChild將dom插入到頁面中 instance.$mount(); let $el = instance.$el; // message彈窗的z-index由popupManager來提供 $el.style.zIndex = popupManager.getNextZIndex(); document.body.appendChild($el); // 將message顯示出來 instance.show = true; console.log(instance) instances.push(instance); return instance; }; // message簡化操作 ["success","error"].forEach(function (item) { Message[item] = options => { if(typeof options === "string"){ options = { message: options } } options.type = item; return Message(options); } }); /** * 從instances刪除指定message,內(nèi)部使用 * @param id * @param userOnClose * @private */ Message._close = function (id, userOnClose) { for(var i = 0, len = instances.length; i < len; i++){ if(instances[i].id === id){ if(typeof userOnClose === "function"){ userOnClose(instances[i]); } instances.splice(i, 1); break; } } }; // 關(guān)閉所有message Message.closeAll = function () { for(var i = instances.length - 1; i >= 0; i--){ instances.close(); } }; export default Message;
popup-manager.js
let zIndex = 1000; let hasZIndexInited = false; const popupManager = { // 獲取索引 getNextZIndex(){ if(!hasZIndexInited){ hasZIndexInited = true; return zIndex; } return zIndex++; } }; export {popupManager};
p-index.js
import pMessage from "./p-message.js"; export default pMessage;
p-message.styl
.p-message{ position: fixed; top: 20px; left: 50%; padding: 8px 15px; border-radius: 4px; background-color: #fff; color: #000; transform: translateX(-50%); transition: opacity .3s, transform .4s; &.message-fade-enter, &.message-fade-leave-to{ opacity: 0; transform: translateX(-50%) translateY(-30px); } &.message-fade-enter-to, &.message-fade-leave{ opacity: 1; transform: translateX(-50%) translateY(0); } &.error{ color: #ff3737; } .p-message-icon{ /* 使圖標與內(nèi)容能夠垂直居中 */ display: table-cell; vertical-align: middle; width: 64px; height: 45px; &.p-message-icon-success{ background: url("../../assets/images/icons/message-icon/icon_success.png") no-repeat 0 0; } &.p-message-icon-error{ background: url("../../assets/images/icons/message-icon/icon_error.png") no-repeat 0 0; } } .p-message-content{ /* 使圖標與內(nèi)容能夠垂直居中 */ display: table-cell; vertical-align: middle; padding-left: 15px; } }
main.js
// 引入pMessage組件 import pMessage from "./components/p-message/p-index.js"; // 將pMessage綁定到Vue.prototype中。這樣在組件中就可以通過this.$pMessage()的形式來使用了 Vue.prototype.$pMessage = pMessage;3、參考
參考了 Element-UI 的message代碼
封裝Vue組件的一些技巧
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/103698.html
摘要:根據(jù)組件單向數(shù)據(jù)流和和事件通信機制,需要由子組件通過事件通知父組件,并在父組件中修改原始的數(shù)據(jù),完成狀態(tài)的更新。 本文同步在個人博客shymean.com上,歡迎關(guān)注 寫Vue有很長一段時間了,除了常規(guī)的業(yè)務開發(fā)之外,也應該思考和反思一下封裝組件的正確方式。以彈窗組件為例,一種實現(xiàn)是在需要模板中引入需要彈窗展示的組件,然后通過一個flag變量來控制彈窗的組件,在業(yè)務代碼里面會充斥著冗余的彈...
摘要:組件顯示隱藏由內(nèi)部屬性控制,只暴露給外界和個方法,個方法觸發(fā)對應的事件測試一下彈窗內(nèi)容插件化組件功能寫好了,但是這種調(diào)用方式顯得很累贅。我們寫的彈窗能不能這么方便呢,為此需要把改寫成插件。 vue做移動端經(jīng)常碰到彈窗的需求, 這里寫一個功能簡單的vue彈窗 popup.vue {{text}} 組件html結(jié)構(gòu), 外層divposition:fixed定位, 內(nèi)...
摘要:在組件內(nèi),我們觸及不到組件的模板,所以簡單的在動態(tài)模板上添加并不能完成事件監(jiān)聽。簡單來說,依賴收集是在渲染函數(shù)渲染的函數(shù)中進行的,在中一旦通過使用了這個變量,通過這個變量的就收集到了正在執(zhí)行的渲染函數(shù)這一個依賴。 作為一個中后臺表單&表格工程師,經(jīng)常需要在一個頁面中處理多個彈窗。我自己的項目中,一個復雜的審核頁面中的彈窗數(shù)量超過了30個,如何管理大量的彈窗就成為了一個需要考慮的問題。 ...
摘要:一簡單的使用主要用于需要動態(tài)渲染的組件,或者類似于提示組件注意創(chuàng)建的是一個組件構(gòu)造器,而不是一個具體的組件實例屬于的全局,在實際業(yè)務開發(fā)中我們很少使用,因為相比常用的寫法使用步驟要更加繁瑣一些。 最近在重構(gòu)公司的項目,有些組件想要封裝的更靈活,例如toast、loading、messageBox等彈窗組件,模仿了mint-ui封裝此類組件的方式封裝了自己的彈窗組件; mint-UI的t...
摘要:組件結(jié)構(gòu)同組件結(jié)構(gòu)通過方法獲取元素的大小及其相對于視口的位置,之后對提示信息進行定位。可以用來進行一些復雜帶校驗的彈窗信息展示,也可以只用于簡單信息的展示。可以通過屬性來顯示任意標題,通過屬性來修改顯示區(qū)域的寬度。 手把手教你擼個vue2.0彈窗組件 在開始之前需要了解一下開發(fā)vue插件的前置知識,推薦先看一下vue官網(wǎng)的插件介紹 預覽地址 http://haogewudi.me/k...
閱讀 3055·2023-04-26 02:27
閱讀 2770·2021-11-22 13:54
閱讀 909·2021-11-12 10:36
閱讀 3764·2021-10-09 09:44
閱讀 3186·2021-10-09 09:41
閱讀 1231·2021-09-22 10:02
閱讀 2842·2019-08-30 15:56
閱讀 3110·2019-08-30 11:02