其实很早之前就想尝试着写一写vue组件然后发布npm包,这次借着公司开发新项目,于是封装了一个Toast组件。
我封装的都是通过vue提供的方法去封装的,但其实从JavaScript的角度去实现或许会更简单,性能也可能更好,不过我只是封装vue组件,有大牛愿意指点的话感激不尽。
Vue.extend:
使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象,简单讲可以理解成继承。然后可以通过挂载$mount到一个元素上面。也可以通过new来声明这个构造器,这样的话跟new Vue是一样的。
首先在一个空文件夹里面npm init,初始化你想要发布的包。
我的项目结构:
外层的index.js:
import Toast from './lib/Toast'
export {
Toast
}
Toast里面main.vue:
<template>
<divv-if="showWrap" :class="showContent ?'fadein':'fadeout'">{{text}}</div>
</template>
<style scoped>
.wrap{
z-index: 100;
position: fixed;
left: 50%;
top:50%;
background: rgba(0,0,0,.6);
padding: 6px;
border-radius: 5px;
transform: translate(-50%,-50%);
color:#fff;
}
.fadein {
animation: in 0.5s;
}
.fadeout {
animation: out 0.5s;
opacity: 0;
}
@keyframes in {
0% {
opacity: 0;
}
100%{
opacity: 1;
}
}
@keyframes out {
0% {
opacity: 1;
}
100%{
opacity: 0;
}
}
</style>
这边加了一点动画。
Toast里面的index.js:
import Vue from 'vue'
import main from './main'
const ToastConstructor = Vue.extend(main)
function Toast(text, duration = 2000) {
const toastDom = new ToastConstructor({
el: document.createElement('div'),
data() {
return {
text:text,
showWrap:true,
showContent:true
}
}
})
document.body.appendChild(toastDom.$el)
// 提前执行动画
setTimeout(() => {toastDom.showContent = false} ,duration - 1500)
setTimeout(() => {
toastDom.showWrap = false;
document.body.removeChild(toastDom.$el);
} ,duration)
}
export default Toast
这个是重点,我们先创建构造器
const ToastConstructor = Vue.extend(main)
我在方法里通过new来声明,我之前说过,这跟new Vue是一样的,没有是吗区别。可以打印出来看看。
el 是我们挂载的元素,new Vue的时候也需要有个挂载元素。当然也可以通过$mount来挂载,两个也没什么区别。
然后我发布到body上面,文字需要提前执行动画,否则这个标签用if直接就隐藏了。
这边要特别注意,我们在隐藏之后,要是再次调用这个组件,没有通过remove移除,页面会有很多注释的空标签。
还有一个注意的是,我每次执行这个方法都会实例化一个toastDom,有些就想着判断是否已经存在,存在就不实例化,可以是可以,但是这个就会出现一个问题就是不能同时触发这个弹窗。
还有一个要注意的,我这样的写法是每个组件都要import Vue,如果是多个组件的话建议把这些方法放到同一个js里面,这样就可以避免重复引入,但是我觉得不影响,可以根据个人习惯去写。
调用的话跟普通UI库一样:
引入:import {Toast} from './wade-ui'
调用:Toast(‘弹窗’,4000);
这就是简单封装的Toast的vue组件,后续会慢慢写一些组件,npm包地址:
https://www.npmjs.com/package/wade-ui
欢迎关注Coding个人笔记 公众号
网友评论