Vue3實現Message訊息元件示例
目錄
- 元件設計
- 定義最終的元件 API
- 定義元件結構
- 模板和樣式
- 模板 Template
- 訊息圖示
- 樣式
- 元件指令碼
- 建立元件例項
- 1、建立包裹容器,並設定外層的 Class 屬性
- 2、建立例項並掛載到 body
- 3、其中定義取消掛載和重新設定 top 值的方法
- 實現渲染例項 API
在大多數 web 產品中,全域性的 Message 元件佔有較大的使用場景,它常出現在給與使用者反饋、資訊提示和與系統的對話場景中。如果使用傳統的元件寫法,則需要引入元件並在 components 中註冊,然後再去模板中以標籤的形式呼叫,傳入自定義 props 屬性並通過 emiqTNUdGmvbt 觸發事件,這類的元件往往有以下缺點:
- 需要頻繁引入並註冊
- 需要在模板中以標籤的形式使用元件
- 需要額外的引數控制組件的屬性和狀態
- 不能友好的自定義元件的掛載位置,會被其他元件影響
因此對於 Message 這類的元件,我們希望可以在 javascript 中呼叫,可以傳入自定義引數控制組件狀態,並且無需在呼叫的時候手動掛載元件到 body 尾部。如果你使用過主流第三方庫,例如 ElementUI plus 或 Ant Design for vue, 那麼你肯定熟悉他們的訊息元件 API,接下來就一起用 Vue3 實現一個全域性的 Message 元件吧。
元件最終實現效果
元件設計
定義最終的元件 API
實現一個簡易的 Message 訊息元件,包含型別 API 有文字(text)、成功(success)、失敗(error),即支援直接傳入一段文字,也支援通過元件具體的 option 配置,來自定義訊息內容、關閉延遲、以及是否展示關閉按鈕等功能。
// Message 型別(type):文字、成功、失敗 ["text","success","error"] // Message 選項(option) [String]: 訊息內容 [Object]: 訊息配置 // option 配置 text [String] "" 訊息內容 duration [Number] 0 自動關閉延遲毫秒數,0為不自動關閉 close [Boolean] false 是否展示關閉按鈕 // 呼叫方式 Message[type](option);
呼叫示例
Message.text("這是一條訊息提示"); Message.error({ text: "網路錯誤,請稍後再試",duration: 3000,close: true });
定義元件結構
建立 Message 資料夾儲存元件的整體結構,其中 src 中包含元件的模板、樣式和例項檔案,同級下,建立 index.js 將整個元件暴露出去,以便在專案和業務元件中引入。
|--- Message |--- src | |--- Message.vue // 元件模板 | |--- Message.less // 提供元件樣式支援 | |--- Message.js // 讀取配置並渲染元件例項 | |--- Instance.js // 元件例項 |---index.js // 暴露元件
模板和樣式
模板 Template
模板相對來說比較簡單,外層由動畫元件包裹,通過 v-show 去控制訊息顯示和關閉,內容部分包括圖示、訊息文字、以及可配置的手動關閉按鈕。
<template>
<!-- 訊息列表 -->
<transition name="slide-fade">
<div class="message-container" v-show="visibled">
<!-- 內容 -->
<div class="message-content">
<!-- 訊息型別圖示,通過訊息型別確定,text型別不配置圖示 -->
<div class="message-icon" v-if="config.icon">
<i :class="config.icon"></i>
</div程式設計客棧>
<!-- 訊息文字 -->
<span v-text="config.content"></span>
<!-- 手動關閉訊息 -->
<div class="option" v-if="!config.close">
<i class="ri-close-fill" @click="onClose"></i>
</div>
</div>
</div>
</transition>
</template>
訊息圖示
需要注意的是,圖示是由呼叫 API 中的型別確定,在建立例項的時候確定圖示型別,這裡引用的是開源圖示庫 Remix Icon,具體的引用方法這裡不多贅述,地址:remixicon.cn/
樣式
在 Message.less 中定義樣式和動畫。
@radius: 4px;
@normalHeight: 34px;
.message {
position: fixed;
top: 0;
left: 0;
width: 100%;
text-align: center;
box-sizing: border-box;
z-index: 9999;
transform: translateZ(9999px);
padding-top: 28px;
transition: top .4s ease;
.message-container {
margin-bottom: 14px;
.message-icon {
display: inline-block;
i {
font-size: 18px;
font-weight: 400;
margin-top: -3px;
margin-right: 6px;
display: inline-block;
box-sizing: border-box;
vertical-align: middle;
}
.ri-checkbox-circle-fill {
color: #58c05b;
}
.ri-close-circle-fill {
color: #fd4f4d;
}
.message-content {
display: inline-block;
padding: 4px 18px;
height: @normalHeight;
text-align: left;
line-height: @normalHeight;
font-size: 14px;
font-weight: 400;
border-radius: @radius;
color: #595959;
box-shadow: 0 4px 12px rgba(0,.15);
background: #ffffff;
.option {
display: inline-block;
pointer-events: all;
margin-left: 18px;
i {
font-size: 18px;
font-weight: 400;
margin-top: -3px;
display: inline-block;
box-sizing: border-box;
vertical-align: middle;
cursor: pointer;
color: #d9d9d9;
transition: color 0.2s ease;
&:hover {
color: #ff7c75;
transition: color 0.2s ease;
}
}
}
}
}
.slide-fade-enter-active {
transition: all .2s ease-out;
}
.slide-fade-leave-active {
transition: all .2s ease;
}
.slide-fade-enter-from,.slide-fade-leave-to {
transform: translateY(-20px);
opacity: 0程式設計客棧;
}
}
元件指令碼
元件中通過獲取傳入的config配置和remove實現渲染和取消掛載,通過onOpen和onClose方法控制訊息開啟和手動關閉,具體程式碼如下:
<script> import { reactive,toRefs } from "vue"; export default { props: { config: { type: Object,default: () => {} },// 訊息配置項 remove: { type: Function,// 取消掛載回撥 },setup(props) { const state = reactive({ visibled: false,}) // 開啟訊息 const onOpen = (config) => { setTimeout(() => { state.visibled = true; },10) // 指定時間後移除訊息 if (config.duration !== 0) { setTimeout(() => { onClose(); },config.duration); } } onOpen(props.config) // 訊息關閉 const onClose = () => { state.visibled = false; setTimeout(() => { props.remove() },200) }; return { ...toRefs(state),onOpen,onClose,}; },}; </script>
建立元件例項
接下來將在 Instance.js 中編寫元件呼叫時建立、掛載、銷燬元件等 API,頭部引入 Vue 的建立例項方法和上面寫好的元件模板:
import { createApp } from 'vue' import Message from './Message.vue'
宣告例項操作方法,接受一個訊息配置引數cfg
/** * Message 例項操作 * @param {Object} cfg 例項配置 */ const createInstance = cfg => { const config = cfg || {} // 1、建立包裹容器,並設定外層的 Class 屬性、訊息計數 // 2、建立例項並掛載到 body // 3、實現取消掛載方法,和取消掛載後重新計數 } export default createInstance
1、建立包裹容器,並設定外層的 Class 屬性
建立一個 DIV 作為外層容器包裹元件,並設定對應 class 屬性
let messageNode = document.createElement('div') let attr = document.createAttribute("class") attr.value = "message" messageNode.setAttributeNode(attr)
訊息計數,我們定義一個訊息彈框的高度為 54 px,在多個訊息排隊開啟的時候,通過設定 top 值使各元件錯開。
const height = 54 // 單個訊息框高度 const messageList = document.getElementsByClassName('message') messageNode.style.top = `${messageList.length * height}px`
2、建立例項並掛載到 body
const app = createApp(Message,{ config,remove() { handleRemove()// 移除元素,訊息關閉後從 Dom 上取消掛載並移除 } }) // 掛載例項並追加到 body 結尾 app.vm = app.mount(messageNode) doc程式設計客棧ument.body.appendChild(messageNode) app.close = () => { handleRemove() } return app
3、其中定義取消掛載和重新設定 top 值的方法
const handleRemove = ()=>{ app.unmount(messageNode) document.body.removeChild(messageNode) resetMsgTop() } const resetMsgTop = () => { for (let i = 0; i < messageList.length; i++) { messageList[i].style.top = `${i * height}px` } }
實現渲染例項 API
通過 Message.js 去讀取配置並渲染。
import createInstance from './Instance.js' /** * 讀取配置並渲染 Message * @param {Object} typeCfg 型別配置 * @param {Object/String} cfg 自定義配置 */ function renderMsg(typeCfg = {},cfg = '') { // 允許直接傳入訊息內容,因此要判斷傳入的 cfg 型別 const isContent = typeof cfg === 'string' // 整合自定義配置 cfg = isContent ? { content: cfg } : cfg const config = Object.assign({},typeCfg,cfg) // 合併配置 const { type = 'text',// 訊息型別 content = '',// 訊息內容 duration = 3000,// 自動關閉延遲時間 close = false // 是否顯示關閉按鈕 } = config // 建立例項 return createInstance({ type,content,duration,close }) }
暴露text、success、error等 API。
export default { // 純文字訊息 text(cfg = "") { const textCfg = { type: "text",icon: '' } return renderMsg(textCfg,cfg); },// 成功提示 success(cfg = "") { const successCfg = { type: "success",icon: 'ri-checkbox-circle-fill' } return renderMsg(successCfg,// 錯誤提示 error(cfg = "") { const errorCfg = { type: "error",icon: 'ri-close-circle-fill' } return renderMsg(errorCfg,}
最後,在最外層的index.js中開放這個元件以供呼叫。
import Message from './src/Message.js'; export def程式設計客棧ault Message;
到此這篇關於 Vue3實現Message訊息元件示例的文章就介紹到這了,更多相關Vue3 Message訊息元件內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!