国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

Vue3實(shí)現(xiàn)Message消息組件示例

瀏覽:82日期:2022-09-28 16:59:56
目錄組件設(shè)計(jì)定義最終的組件 API定義組件結(jié)構(gòu)模板和樣式模板 Template消息圖標(biāo)樣式組件腳本創(chuàng)建組件實(shí)例1、創(chuàng)建包裹容器,并設(shè)置外層的 Class 屬性2、創(chuàng)建實(shí)例并掛載到 body3、其中定義取消掛載和重新設(shè)置 top 值的方法實(shí)現(xiàn)渲染實(shí)例 API

在大多數(shù) web 產(chǎn)品中,全局的 Message 組件占有較大的使用場(chǎng)景,它常出現(xiàn)在給與用戶反饋、信息提示和與系統(tǒng)的對(duì)話場(chǎng)景中。如果使用傳統(tǒng)的組件寫法,則需要引入組件并在 components 中注冊(cè),然后再去模板中以標(biāo)簽的形式調(diào)用,傳入自定義 props 屬性并通過 emit 觸發(fā)事件,這類的組件往往有以下缺點(diǎn):

需要頻繁引入并注冊(cè) 需要在模板中以標(biāo)簽的形式使用組件 需要額外的參數(shù)控制組件的屬性和狀態(tài) 不能友好的自定義組件的掛載位置,會(huì)被其他組件影響

因此對(duì)于 Message 這類的組件,我們希望可以在 JavaScript 中調(diào)用,可以傳入自定義參數(shù)控制組件狀態(tài),并且無需在調(diào)用的時(shí)候手動(dòng)掛載組件到 body 尾部。如果你使用過主流第三方庫,例如 ElementUI plus 或 Ant Design for Vue, 那么你肯定熟悉他們的消息組件 API,接下來就一起用 Vue3 實(shí)現(xiàn)一個(gè)全局的 Message 組件吧。

組件最終實(shí)現(xiàn)效果

Vue3實(shí)現(xiàn)Message消息組件示例

組件設(shè)計(jì)定義最終的組件 API

實(shí)現(xiàn)一個(gè)簡(jiǎn)易的 Message 消息組件,包含類型 API 有文本(text)、成功(success)、失敗(error),即支持直接傳入一段文本,也支持通過組件具體的 option 配置,來自定義消息內(nèi)容、關(guān)閉延遲、以及是否展示關(guān)閉按鈕等功能。

// Message 類型(type):文本、成功、失敗['text', 'success', 'error']// Message 選項(xiàng)(option)[String]: 消息內(nèi)容[Object]: 消息配置// option 配置text [String] '' 消息內(nèi)容duration [Number] 0 自動(dòng)關(guān)閉延遲毫秒數(shù),0為不自動(dòng)關(guān)閉close [Boolean] false 是否展示關(guān)閉按鈕// 調(diào)用方式Message[type](option);

調(diào)用示例

Message.text('這是一條消息提示');Message.error({ text: '網(wǎng)絡(luò)錯(cuò)誤,請(qǐng)稍后再試', duration: 3000, close: true});定義組件結(jié)構(gòu)

建立 Message 文件夾存儲(chǔ)組件的整體結(jié)構(gòu),其中 src 中包含組件的模板、樣式和實(shí)例文件,同級(jí)下,建立 index.js 將整個(gè)組件暴露出去,以便在項(xiàng)目和業(yè)務(wù)組件中引入。

|--- Message |--- src | |--- Message.vue // 組件模板 | |--- Message.less // 提供組件樣式支持 | |--- Message.js // 讀取配置并渲染組件實(shí)例 | |--- Instance.js // 組件實(shí)例 |---index.js // 暴露組件模板和樣式模板 Template

模板相對(duì)來說比較簡(jiǎn)單,外層由動(dòng)畫組件包裹,通過 v-show 去控制消息顯示和關(guān)閉,內(nèi)容部分包括圖標(biāo)、消息文本、以及可配置的手動(dòng)關(guān)閉按鈕。

<template> <!-- 消息列表 --> <transition name='slide-fade'> <div v-show='visibled'> <!-- 內(nèi)容 --> <div class='message-content'><!-- 消息類型圖標(biāo),通過消息類型確定,text類型不配置圖標(biāo) --><div v-if='config.icon'> <i :class='config.icon'></i></div> <!-- 消息文本 --><span v-text='config.content'></span><!-- 手動(dòng)關(guān)閉消息 --><div v-if='!config.close'> <i @click='onClose'></i></div> </div> </div> </transition></template>消息圖標(biāo)

需要注意的是,圖標(biāo)是由調(diào)用 API 中的類型確定,在創(chuàng)建實(shí)例的時(shí)候確定圖標(biāo)類型,這里引用的是開源圖標(biāo)庫 Remix Icon,具體的引用方法這里不多贅述,地址:remixicon.cn/

樣式

在 Message.less 中定義樣式和動(dòng)畫。

@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, 0, 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實(shí)現(xiàn)渲染和取消掛載,通過onOpen和onClose方法控制消息打開和手動(dòng)關(guān)閉,具體代碼如下:

<script>import { reactive, toRefs } from 'vue';export default { props: { config: { type: Object, default: () => {} }, // 消息配置項(xiàng) remove: { type: Function, default: () => {} }, // 取消掛載回調(diào) }, setup(props) { const state = reactive({ visibled: false, }) // 打開消息 const onOpen = (config) => { setTimeout(() => {state.visibled = true; }, 10) // 指定時(shí)間后移除消息 if (config.duration !== 0) {setTimeout(() => { onClose();}, config.duration); } } onOpen(props.config) // 消息關(guān)閉 const onClose = () => { state.visibled = false; setTimeout(() => {props.remove() }, 200) }; return { ...toRefs(state), onOpen, onClose, }; },};</script>創(chuàng)建組件實(shí)例

接下來將在 Instance.js 中編寫組件調(diào)用時(shí)創(chuàng)建、掛載、銷毀組件等 API,頭部引入 Vue 的創(chuàng)建實(shí)例方法和上面寫好的組件模板:

import { createApp } from ’vue’import Message from ’./Message.vue’

聲明實(shí)例操作方法,接受一個(gè)消息配置參數(shù)cfg

/** * Message 實(shí)例操作 * @param {Object} cfg 實(shí)例配置 */const createInstance = cfg => { const config = cfg || {} // 1、創(chuàng)建包裹容器,并設(shè)置外層的 Class 屬性、消息計(jì)數(shù) // 2、創(chuàng)建實(shí)例并掛載到 body // 3、實(shí)現(xiàn)取消掛載方法,和取消掛載后重新計(jì)數(shù)}export default createInstance1、創(chuàng)建包裹容器,并設(shè)置外層的 Class 屬性

創(chuàng)建一個(gè) DIV 作為外層容器包裹組件,并設(shè)置對(duì)應(yīng) class 屬性

let messageNode = document.createElement(’div’)let attr = document.createAttribute('class')attr.value = 'message'messageNode.setAttributeNode(attr)

消息計(jì)數(shù),我們定義一個(gè)消息彈框的高度為 54 px,在多個(gè)消息排隊(duì)打開的時(shí)候,通過設(shè)置 top 值使各組件錯(cuò)開。

const height = 54 // 單個(gè)消息框高度const messageList = document.getElementsByClassName(’message’)messageNode.style.top = `${messageList.length * height}px`2、創(chuàng)建實(shí)例并掛載到 body

const app = createApp(Message, { config, remove() { handleRemove()// 移除元素,消息關(guān)閉后從 Dom 上取消掛載并移除 }})// 掛載實(shí)例并追加到 body 結(jié)尾app.vm = app.mount(messageNode)document.body.appendChild(messageNode)app.close = () => { handleRemove()}return app3、其中定義取消掛載和重新設(shè)置 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` }}實(shí)現(xiàn)渲染實(shí)例 API

通過 Message.js 去讀取配置并渲染。

import createInstance from ’./Instance.js’/** * 讀取配置并渲染 Message * @param {Object} typeCfg 類型配置 * @param {Object/String} cfg 自定義配置 */function renderMsg(typeCfg = {}, cfg = ’’) { // 允許直接傳入消息內(nèi)容,因此要判斷傳入的 cfg 類型 const isContent = typeof cfg === ’string’ // 整合自定義配置 cfg = isContent ? { content: cfg } : cfg const config = Object.assign({}, typeCfg, cfg) // 合并配置 const { type = ’text’, // 消息類型 content = ’’, // 消息內(nèi)容 duration = 3000, // 自動(dòng)關(guān)閉延遲時(shí)間 close = false // 是否顯示關(guān)閉按鈕 } = config // 創(chuàng)建實(shí)例 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, cfg); }, // 錯(cuò)誤提示 error(cfg = '') { const errorCfg = { type: 'error', icon: ’ri-close-circle-fill’ } return renderMsg(errorCfg, cfg); },}

最后,在最外層的index.js中開放這個(gè)組件以供調(diào)用。

import Message from ’./src/Message.js’;export default Message;

到此這篇關(guān)于 Vue3實(shí)現(xiàn)Message消息組件示例的文章就介紹到這了,更多相關(guān)Vue3 Message消息組件內(nèi)容請(qǐng)搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 亚洲视频在线免费看 | 国产三级视频在线 | 国产成人丝袜网站在线看 | 女人张开腿让男人桶免费最新 | 在线亚洲精品国产成人二区 | 自拍偷自拍亚洲精品一区 | 在线播放免费一级毛片欧美 | 午夜伊人网 | 欧美jizzhd欧美精品 | 国产在线一区二区三区欧美 | 日韩欧美在线一级一中文字暮 | 美女张开腿让男人 | 99久久国产综合精品1尤物 | 在线a国产 | 欧美在线一区二区三区不卡 | 亚洲免费精品 | 特级毛片aaa免费版 特级毛片a级毛免费播放 | 欧美成人精品一区二区三区 | 国产成人午夜性视频影院 | 久久久久久综合成人精品 | 精品国产免费一区二区三区五区 | www.成人网 | 国产成人亚洲综合欧美一部 | 自拍视频在线观看 | 精品无码三级在线观看视频 | 国产精品久久永久免费 | a高清免费毛片久久 | 中文精品久久久久国产不卡 | 在线色网址 | 亚洲精品国产第一区二区三区 | 欧美成人午夜视频免看 | 成人福利在线 | 亚洲欧美日本在线 | 久久久久国产精品美女毛片 | 呦女亚洲一区精品 | 国产精品一区二区资源 | 看毛片的网址 | 一级全黄视频 | 亚洲区精品久久一区二区三区 | 国产成人aa在线视频 | 精品国产免费人成高清 |