一、创建this.$toast
- css尽量都不要写进js里面;
1、 Vue.prototype.$toast = function(){},然后你就可以用this.$toast()
import Vue from 'vue'
Vue.prototype.$toast = function(){
console.log('toast')
}
2、有两个问题,一是直接这样引入Vue好不好;二是在Vue的prototype上定义$toast会不会覆盖掉原有的属性;这两个属于工程问题(就是在工程项目中会实际发生的问题),所以需要使用Vue的插件来解决以上两个问题(可见文档);
二、使用Vue的插件功能
-
动态创建实例,生成一个toast组件,放在body里面,参考知乎文章;
动态创建实例.png
-
如果你用vue,想append进页面一个元素,那么一定优先append进一个组件,不要直接append进一个div;好处的话,绑定事件会方便很多;
-
this.$el.remove()
把元素从body里拿出来;this.$destory()
然后自己再毁灭掉; -
如果你的props是个对象或数组,那么default值不能直接写成
{}
或[]
,要写成一个函数,return出来(跟组件的data形式一样) -
css问题,有时候你观察到高度的不是0,但打印出来是0,一般就是异步的问题(用
vm.$nextTick(()=>{})
解决); -
把toast的height改成min-height后,出现了一个css上的bug,右边那条线高度撑不起来了,所以我们就不得不通过js去操控css,给线加上高度;通过ref来获取toast的高度值;(
vm.$nextTick(()=>{})
意思是回调会在DOM更新之后执行)
this.$nextTick(()=>{
this.$refs.line.style.height = `${this.$refs.toast.getBoundingClientRect().height}px`
})
this.$refs.toast.getBoundingClientRect()
getBoundingClientRect.png
-
高度不定的flex元素,里面的子元素高度定100%是没有用的(最小高度不算高度)
-
设置位置属性时,上下中间叫middle,左右中间叫center;
-
最好用indexOf,不用includes(indexOf兼容性更好一些)
三、禁止多个toast同时出现
1、先重构一下plugin.js里的代码,把创建toast实例写成一个函数,再把toast实例return出来,每次创建实例前都要先检查一下body中是否已有这个实例了,有的话就把它销毁,然后再创建新的实例,这样就做到了禁止多个toast同时出现;
2、其实这里有一个小bug,组件是被销毁了,但是currentToast这个值还在,没有被清空啊!!!所以在销毁toast的时候,触发一个close事件,外面监听一下,一旦监听到close事件了,就把currentToast赋值为null;
//plugin.js
import Toast from './toast.vue'
let currentToast
export default {
install(Vue,options){ //我没有引Vue,Vue是从哪来的? 通过Vue.use()传来的
Vue.prototype.$toast = function(message,toastOptions){ //这里括号里的是$toast的属性参数
if(currentToast){
currentToast.close() //组件是被销毁了,但是currentToast这个值还在啊!!!!
}
currentToast = createToast(Vue,message,toastOptions,()=>{currentToast = null})
}
}
}
//下面这里传{Vue,message,toastOptions,onClose}或直接写都可以,主要在于你调用时参数的写法会不同,仅此而已
function createToast(Vue,message,toastOptions,onClose){
let Constructor = Vue.extend(Toast)
let toast = new Constructor({
propsData: toastOptions
})
toast.$slots.default = message
toast.$mount() //slot要放在mount之前
toast.$on('close',onClose)
document.body.appendChild(toast.$el)
return toast
}
//toast.vue
close(){
this.$el.remove()
this.$emit('close')
this.$destroy()
},
网友评论