We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
本文写于2017.3.15
最近写的 Vue-Friendship 中,一直不知道如何去优雅地实现toast,今天翻了下mint-ui的toast,发现一个小小的toast也是要复杂的代码去实现,这篇文章就是来分析一下mint-ui中toast的源码。
toast
可以先看看其中的文件目录
└─toast │ index.js │ README.md │ └─src toast.js toast.vue
最上层的是toast文件夹,里面有一个index.js出口,里面的代码很简单,就是把./src/toast.js往外暴露。
index.js
./src/toast.js
export { default } from './src/toast.js';
这个文件是放着的是vue模板,以及一些props。其中vue的模板对有无icon的情况做了下兼容,这个不是重点可以自己去看看,下面来看下props
props: { message: String, className: { type: String, default: '' }, position: { type: String, default: 'middle' }, iconClass: { type: String, default: '' } }, data() { return { visible: false }; },
在这里,定义了四个props,分别是类名className、位置position以及icon的类iconClass。这里有个visible的data属性,控制toast的出现与消失。
className
position
iconClass
visible
在下面的computed中,根据position的不同分别给了不同的类从而实现位置的变化,接着拼接整个className。最后整个通过export default导出。
export default
toast.js是实现toast的重点。
toast.js
先是通过Vue.extend,将toast.vue引入,并创建一个Vue的组件构造函数。 接着定义一个toastPool数组作为实例池,用于存储已创建的toast实例。
Vue.extend
toast.vue
toastPool
// 创建组件构造函数 const ToastConstructor = Vue.extend(require('./toast.vue')); // 定义一个实例池 let toastPool = [];
定义一个函数,用于获取实例
let getAnInstance = () => { // 如果实例池中有实力,则不建立新的实例 if (toastPool.length > 0) { let instance = toastPool[0]; // 每当从实例池取走一个实例,则删除这个实例 toastPool.splice(0, 1); return instance; } // 如果没有,建立新的实例 return new ToastConstructor({ el: document.createElement('div') }); };
这两个函数比较简单,returnAnInstance是把实例返回给实例池
returnAnInstance
let returnAnInstance = instance => { if (instance) { // 直接push就可以 toastPool.push(instance); } };
removeDom则是在toast结束后删除此Dom,这里不详讲。
removeDom
在这个函数,把本实例visible设为false,然后绑定一个transitionend事件。这个事件会在通过transition的动画结束后,则执行removeDom。然后设置closed为true,最后把实例返回到实例池中保存起来。
transitionend
transition
ToastConstructor.prototype.close = function() { // toast不可见 this.visible = false; // 绑定事件,在动画结束后执行删除dom的动作 this.$el.addEventListener('transitionend', removeDom); // 设置已结束 this.closed = true; // 返回实例池 returnAnInstance(this); };
在mint-ui中,这个是Vue.$toast的入口。
Vue.$toast
// 如果没有options,定义一个options let Toast = (options = {}) => { // 定义延时 let duration = options.duration || 3000; // 获取一个实例 let instance = getAnInstance(); instance.closed = false; // 清除定时器 clearTimeout(instance.timer); // 下面几个是设置props instance.message = typeof options === 'string' ? options : options.message; instance.position = options.position || 'middle'; instance.className = options.className || ''; instance.iconClass = options.iconClass || ''; // 把dom插入body中 document.body.appendChild(instance.$el); Vue.nextTick(function() { // 设置为可见 instance.visible = true; // 把dom上绑定的removeDom先移除 instance.$el.removeEventListener('transitionend', removeDom); // 打开定时器 ~duration && (instance.timer = setTimeout(function() { if (instance.closed) return; // 结束后执行close instance.close(); }, duration)); }); // 返回实例 return instance; };
最后通过export default往外暴露Toast函数
在Toast中,有一个Vue.nextTick。 在Vue中,修改了data后,被绑定的视图不会立马更新。在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
Vue.nextTick
// e.g var vm = new Vue({ el: '#example', data: { msg: '123' } }) vm.msg = 'new message' // change data vm.$el.textContent === 'new message' // false Vue.nextTick(function() { vm.$el.textContent === 'new message' // true })
在mint-ui/src/inde中绑定在Vue上
mint-ui/src/inde
import Toast from '../packages/toast'; Vue.$toast = Vue.prototype.$toast = Toast;
这样就可以直接通过Vue.$toast优雅地实现toast
The text was updated successfully, but these errors were encountered:
No branches or pull requests
文件目录
可以先看看其中的文件目录
└─toast
│ index.js
│ README.md
│
└─src
toast.js
toast.vue
index.js
最上层的是
toast
文件夹,里面有一个index.js
出口,里面的代码很简单,就是把./src/toast.js
往外暴露。toast.vue
这个文件是放着的是vue模板,以及一些props。其中vue的模板对有无icon的情况做了下兼容,这个不是重点可以自己去看看,下面来看下props
在这里,定义了四个props,分别是类名
className
、位置position
以及icon的类iconClass
。这里有个visible
的data属性,控制toast的出现与消失。在下面的computed中,根据
position
的不同分别给了不同的类从而实现位置的变化,接着拼接整个className。最后整个通过export default
导出。toast.js
创建组件构造函数 && 实例池
先是通过
Vue.extend
,将toast.vue
引入,并创建一个Vue的组件构造函数。接着定义一个
toastPool
数组作为实例池,用于存储已创建的toast实例。getAnInstance()
定义一个函数,用于获取实例
returnAnInstance() && removeDom()
这两个函数比较简单,
returnAnInstance
是把实例返回给实例池removeDom
则是在toast结束后删除此Dom,这里不详讲。ToastConstructor.prototype.close()
在这个函数,把本实例
visible
设为false,然后绑定一个transitionend
事件。这个事件会在通过transition
的动画结束后,则执行removeDom
。然后设置closed为true,最后把实例返回到实例池中保存起来。Toast主函数
在mint-ui中,这个是
Vue.$toast
的入口。最后通过
export default
往外暴露Toast函数Vue.nextTick
在Toast中,有一个
Vue.nextTick
。在Vue中,修改了data后,被绑定的视图不会立马更新。在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
绑定在Vue上
在
mint-ui/src/inde
中绑定在Vue上这样就可以直接通过
Vue.$toast
优雅地实现toastThe text was updated successfully, but these errors were encountered: