Message組件實(shí)現(xiàn)發(fā)財(cái)U(kuò)I?示例詳解
引言
最近在實(shí)現(xiàn)Message組件,就是會(huì)從屏幕頂端彈出的一個(gè)小提醒,過一會(huì)兒就消失了。我個(gè)人非常喜歡這個(gè)設(shè)計(jì),感覺在后續(xù)的復(fù)用性也很高,于是就打算自己手寫一個(gè)作為發(fā)財(cái)U(kuò)I的組件
支持的功能
目前的Message有四種類型:
普通提醒 normal

成功提醒 success

警告提醒 warning

錯(cuò)誤提醒error

同時(shí)還支持設(shè)置持續(xù)的時(shí)間:

使用方法
是不是非常簡(jiǎn)單??
<template>
<div>
<button @click="popNormalMsg">打開一個(gè)普通提醒</button>
</div>
</template>
<script lang="ts">
import {popMessage} from "../../lib/popMessage";
export default {
name: "Message1.demo",
components: {Button},
setup() {
const popNormalMsg = () => {
popMessage({
message: '這是一個(gè)全局顯示的普通提醒', //提醒內(nèi)容
msgType: 'normal', //提醒類型normal success error warning
closeDelay: '2000', //顯示的時(shí)長(zhǎng),以ms為單位
})
}
return {popNormalMsg}
}
}
</script>
實(shí)現(xiàn)過程
如何實(shí)現(xiàn)不同類型的切換?
其實(shí)切換類型只是切換圖標(biāo)而已哈哈哈
這里使用了IconPark圖標(biāo)庫,這里使用了一個(gè)投機(jī)取巧的辦法,把不同的圖標(biāo)命名為相應(yīng)的type,可以節(jié)省一些處理的步驟
| href=#normal | msgType='normal' |
| href=#success | msgType='success' |
| href=#warning | msgType='warning' |
| href=#error | msgType='error' |
const typeIndicator = `<use href="#${props.msgType}" rel="external nofollow" rel="external nofollow" ></use>`
<template>
<div ref="msgDiv" class="rich-message">
<svg class="iconpark-icon" v-html="typeIndicator">
//2??typeIndicator的內(nèi)容會(huì)原封不動(dòng)的跑到這里
</svg>
//3??最后和svg標(biāo)簽一起變成type對(duì)應(yīng)的圖標(biāo)
<div class="rich-message-msgText">{{ message }}</div>
</div>
</template>
<script lang="ts">
export default {
name: "Message",
props: {
message: {
type: String,
required: true,
},
msgType: {
type: String,
default: 'normal',
},
},
setup(props) {
const typeIndicator = `<use href="#${props.msgType}" rel="external nofollow" rel="external nofollow" ></use>`
return {typeIndicator}
//1??接受到傳來的type,然后typeIndicator會(huì)自動(dòng)變?yōu)橄鄳?yīng)的圖標(biāo)use標(biāo)簽
}
}
</script>
如何實(shí)現(xiàn)Message的彈出和消失?
使用了CSS的transform,實(shí)際上就是Message在初始狀態(tài)下是藏在畫面外的,通過添加一個(gè).message-active的類來讓它顯示出來,在經(jīng)過closeDelay毫秒后移除.message-active類。
.rich-message {
...
transform: translateY(-100px);
transition: all 250ms;
&.message-active {
transform: translateY(0px);
opacity: 1;
}
}
如何實(shí)現(xiàn)往下排列而非堆疊?
為了讓他們能夠一個(gè)一個(gè)的排列下來而不是堆疊在一起,我想到了insertAdjacentElement()方法
element.insertAdjacentElement(position, element);
position有下面四種取值
'beforebegin': 在該元素本身的前面。
'afterbegin':只在該元素當(dāng)中,在該元素第一個(gè)子孩子前面。
'beforeend':只在該元素當(dāng)中,在該元素最后一個(gè)子孩子后面。
'afterend': 在該元素本身的后面。
不難發(fā)現(xiàn)這里似乎可以使用beforeend和afterend。經(jīng)過我的思考,為了保持DOM樹的整潔,我采用了創(chuàng)建一個(gè)msgContainer的div來存放所有的Message的方法,因此我也相應(yīng)的使用了beforeend
let msgContainer = document.getElementById('msgDiv')
if (msgContainer === null) {
msgContainer = document.createElement('div')
msgContainer.id = 'msgDiv'
document.body.appendChild(msgContainer)
}
const div = document.createElement('div'); //這個(gè)div就是Message所在的div
msgContainer.insertAdjacentElement('beforeend', div)
給msgContainer一個(gè)CSS樣式
#msgDiv {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
如何實(shí)現(xiàn)添加和移除.message-active類?
如果msgDiv在創(chuàng)建時(shí)就帶有.message-active類,那么將會(huì)閃現(xiàn)在頁面中,所以msgDiv應(yīng)該是在渲染后被添加了.message-active類,為了實(shí)現(xiàn)這個(gè)效果,使用了一個(gè)setTimeout()。
同時(shí)在closeDelay之后將這個(gè)類移除。
但是這樣存在一個(gè)問題,這個(gè)msgDiv只是看不見了,依然存在于DOM樹中。
setTimeout(() => {
msgDiv.classList.add('message-active')
}, 0)
setTimeout(() => {
msgDiv.classList.remove('message-active')
}, closeDelay * 1);
如何將隱藏的Message從DOM樹中移除
在Message的淡出動(dòng)畫結(jié)束后移除就好了,這里使用了.ontransitionendAPI,但是還存在問題,即如果有多個(gè)Message,他們會(huì)同時(shí)消失,原因是雖然每個(gè)Message在創(chuàng)建時(shí)都會(huì)有一個(gè)計(jì)時(shí)器,但是在移除時(shí)卻是所有的msgDiv一起移除,因此需要有區(qū)分的方法。
setTimeout(() => {
msgDiv.classList.remove('message-active')
msgDiv.ontransitionend = () => {
app.unmount();
div.remove();
}
}, closeDelay * 1);
如何區(qū)分不同的Message?
在本項(xiàng)目中,我使用了隨機(jī)生成ID的方式,如此一番就能精準(zhǔn)的控制每個(gè)msgDiv
function randomLetter(len) {
let str = '';
for (let i = 0; i < len; i++) {
str += String.fromCharCode(~~(Math.random() * 26 + 65));
}
return str;
}
const msgId = randomLetter(~~(Math.random() * 10 + 30)) //生成了一個(gè)隨機(jī)字符串
const app = createApp({
render() {
return h(Message, {
message,
msgType,
id: msgId,
});
}
});
app.mount(div);
const msgDiv = document.getElementById(String(msgId))
setTimeout(() => {
msgDiv.classList.add('message-active')
}, 0)
setTimeout(() => {
msgDiv.classList.remove('message-active')
msgDiv.ontransitionend = () => {
app.unmount();
div.remove();
}
}, closeDelay * 1);
最后的一個(gè)小細(xì)節(jié)
我們使用了一個(gè)msgContainer將所有的Message包裹的起來,從而實(shí)現(xiàn)順序排列,但是在最后一個(gè)Message消失后,msgContainer會(huì)作為一個(gè)空的div仍然存在于DOM樹中,這很不環(huán)保,因此在最后一個(gè)Message消失后將msgContainer也一并移除
setTimeout(() => {
msgDiv.classList.remove('message-active')
msgDiv.ontransitionend = () => {
app.unmount();
div.remove();
if (msgContainer.children.length === 0) {
msgContainer.remove()
}
}
}, closeDelay * 1);
以上就是Message組件實(shí)現(xiàn)發(fā)財(cái)U(kuò)I 示例詳解的詳細(xì)內(nèi)容,更多關(guān)于Message組件發(fā)財(cái)U(kuò)I 的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
vue實(shí)現(xiàn)滾動(dòng)條始終懸浮在頁面最下方
這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)滾動(dòng)條始終懸浮在頁面最下方,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04
Element-ui 自帶的兩種遠(yuǎn)程搜索(模糊查詢)用法講解
這篇文章主要介紹了Element-ui 自帶的兩種遠(yuǎn)程搜索(模糊查詢)用法講解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01
Vue2.0父組件與子組件之間的事件發(fā)射與接收實(shí)例代碼
這篇文章主要介紹了Vue2.0父組件與子組件之間的事件發(fā)射與接收實(shí)例代碼,需要的朋友可以參考下2017-09-09
VUE中setTimeout和setInterval自動(dòng)銷毀案例
這篇文章主要介紹了VUE中setTimeout和setInterval自動(dòng)銷毀案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-09-09
關(guān)于配置babel-plugin-import報(bào)錯(cuò)的坑及解決
這篇文章主要介紹了關(guān)于配置babel-plugin-import報(bào)錯(cuò)的坑及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12

