造輪子-toast組件的實現(下)
1.解決 toast 中傳入 html 的問題,通過假的 slot 來實現
// plugins.js
toast.$slots.default = [message]
// toast.vue
<div v-html="$slots.default[0]"></div>
// 使用
created() {
this.$toast('<p>我是<strong>hi</strong></p>',{})
},
2.在 toast 中加 html 是比較危險的一個動作,所以要加一個選項默認不開啟。
// toast.vue
<slot v-if="!enableHtml"></slot>
<div v-else v-html="$slots.default[0]"></div>
// plugin.js,進行傳遞參數的改寫
propsData:toastOptions
// 使用
created() {
this.$toast('<p>我是<strong>hi</strong></p><a href="http://qq.com">qq</a>',{
enableHtml: false
})
},
3.flex-shrink的使用,flex-shrink屬性定義了項目的縮小比例,默認為1,即如果空間不足,該項目將縮小。
.item {
flex-shrink: <number>; /* default 1 */
}
如果所有項目的flex-shrink屬性都為1,當空間不足時,都將等比例縮小。如果一個項目的flex-shrink屬性為0,其他項目都為1,則空間不足時,前者不縮小。如果數值越大,縮小比例越大。
,電腦回收,4.line的高度問題,如果高度寫了最小高度,那麼子元素的height%就不生效了。用js去操作line的高度。
// toast.vue
<div class="toast" ref="wrapper">
<div class="line" ref="line"></div>
</div>
mounted() {
this.$nextTick(()=>{
this.$refs.line.style.height = `${this.$refs.wrapper.getBoundingClientRect().height}px`
})
}, // 這個計較太trick
debugger的技巧,如果眼睛觀察到的是0,但是打印出來不是0,可能就是異步的問題。
5.增加toast的位置。
// toast.vue
props: {
position: {
type: String,
default: 'top',
validator(value){
return ['top', 'bottom', 'middle'].indexOf(value) >= 0
}
}
},
computed:{
toastClasses(){
return {
[`position-${this.position}`]:true
}
}
}
// 使用
this.$toast('你的智商需要充值', {
position: 'bottom'
})
// plugin.js
export default {
install(Vue, options){
Vue.prototype.$toast = function (message, toastOptions) {
let Constructor = Vue.extend(Toast)
let toast = new Constructor({
propsData:toastOptions // 在這裏將position傳進去
})
toast.$slots.default = [message]
toast.$mount()
document.body.appendChild(toast.$el)
}
}
}
6.開始做如果已經有一個toast就把之前那個幹掉,再出現。
- 先寫一個函數
- 給函數取一個名字
- 把參數提出來
// plugin.js
import Toast from './toast'
let currentToast
export default {
install(Vue, options){
Vue.prototype.$toast = function (message, toastOptions) {
if(currentToast){
currentToast.close()
}
currentToast = createToast({Vue,message, propsData: toastOptions})
}
}
}
/* helpers */
function createToast ({Vue,message,propsData}){
let Constructor = Vue.extend(Toast)
let toast = new Constructor({propsData})
toast.$slots.default = [message]
toast.$mount()
document.body.appendChild(toast.$el)
return toast
}
7.實現動畫
- 聲明一個動畫,然後寫到類上面
@keyframes fade {
0% {opacity: 0; transform: translateY(100%);}
100% {opacity: 1;transform: translateY(0);}
}
.toast {
animation: fade 1s;
}
- 這裡有個bug,我們在實現一次的時候是有問題的,如果toast被關閉了,我們不需要重複關閉,而我們寫的是不管你之前的toast有沒有關閉,只要有值的我們就關閉,那這樣就會出現一個問題,點了關閉currentToast還是一個Toast並沒有把它變成null,所以要加上一個回調告訴外面,我被關了不要重複關我,代碼會多調一次close。
// toast.vue
close() {
this.$el.remove()
this.$emit('close')
this.$destroy()
}
// plugin.js
export default {
install(Vue, options){
Vue.prototype.$toast = function (message, toastOptions) {
if(currentToast){
currentToast.close()
}
currentToast = createToast({Vue,message, propsData: toastOptions,onclose: ()=>{
currentToast = null
}
}) // 加了這句話
}
}
}
/* helpers */
function createToast ({Vue,message,propsData,onclose}){
let Constructor = Vue.extend(Toast)
let toast = new Constructor({propsData})
toast.$slots.default = [message]
toast.$mount()
toast.$on('close',onclose) // 加了這句話
document.body.appendChild(toast.$el)
return toast
}
- git相關的鈎上,不想管的不用鈎上
- 回憶bug是如何產生的,默認樣式是:transform:translateX(-50%),進入0%時候transform:translateY(100%),它們兩會覆蓋。有三個方案,解決。
- 換一種方式去做居中,但是這種方法是最好的,很難想
- 不要用css做動畫
- 做兩個div外面一個居中,裏面一個做動畫
- 為什麼不寫兩個動畫幀來控制居中,如果一段代碼要背下來,那麼一定是有問題的。
- 優化三種動畫,上下中是不一樣的,通過css進行優化。
WeihanLi.Npoi 根據模板導出Excel