第二篇:从零开始构建自己的 vue 组件库之————message 组件
组件需求
- message 这种组件应该是按需加载的没差了,用的时候就不要写在页面里了,必须得是 this.$message(config) 这样子用的,姿势很优美 [滑稽];
- 顶部居中吧,既然人家各种框架也是顶部居中,咱也随大流啦,重在理解实现方式啦 [再次滑稽];
- 好了,具体需求是,用不同图标表示不同类型的 message(有默认);时长自定义或默认;内容自定义;可关闭或不可关闭(或点击文字关闭);
PS:组件结构参考上一篇 button 组件
message.vue
<template lang="html">
<transition name="message-fade">
<div class="wui__message" :class="[prefixCls +'--'+ type]" v-if="visible">
<i :class="[prefixCls +'__icon'+'--'+ type,iconType]"></i>
<div :class="[prefixCls +'__content']">
<span :class="[prefixCls +'__content'+'__body']" v-html="content"></span>
<span v-if="closeTxt" @click="close()" :class="[prefixCls +'__closeTxt']">
{{closeTxt}}
</span>
<span v-if="closable" :class="[prefixCls +'__iconbox']">
<i class="icon-close" :class="[prefixCls +'__icon']" @click="close()"></i>
</span>
</div>
</div>
</transition>
</template>
<script>
const prefixCls = 'wui__message';
export default {
name:'Message',
data(){
return {prefixCls:prefixCls,}
},
mounted() {
//do something after mounting vue instance
if(this.closeTxt){this.closable = false}
},
methods: {close() {this.visible = false}
}
}
</script>
<style lang="scss" scoped>
</style>
message 目录下的 index.js
import Vue from 'vue';
import Message from './src/message.vue';
const defaults = {
visible:false,
content:undefined,
duration:'3',
type:'info',
closable:false,
closeTxt:null,
top:20,
iconType:''
};
const typeMap = {
"info":'icon-info',
"error":'icon-heart-broken',
"warning":'icon-stopwatch',
"success":'icon-checkmark-outline'
}
const MessageVueConstructor = Vue.extend(Message);
MessageVueConstructor.prototype.close = function() {
var vm=this;
this.$on('after-leave', _ => {if (vm.$el && vm.$el.parentNode) {vm.$el.parentNode.removeChild(vm.$el);
}
this.$destroy();});
vm.visible = false;
};
const messageBox = (options = {}) => {if (Vue.prototype.$isServer) return;
options = Object.assign({}, defaults, options);
let instance = new MessageVueConstructor({el: document.createElement('div'),
data: options
});
if(!instance.type||!instance.content){return false}
document.body.appendChild(instance.$el);
Vue.nextTick(() => {
instance.visible = true;
instance.iconType = typeMap[instance.type]
// if duration is 0 means can't close
if(instance.duration!=0){setTimeout(function(){instance.close();
},options.duration*1000)
}
});
return instance;
};
export default messageBox;
package 下的 index.js(继上篇增加)
import WButton from './button/index.js';
import WMessage from './message/index';
const components = [
WButton,
WMessage
]
const install = function(Vue) {if (install.installed) return
components.map(component => Vue.component(component.name, component))
Vue.prototype.$Message = WMessage; //important
}
if (typeof window !== 'undefined' && window.Vue) {install(window.Vue)
}
export default {
install,
WButton,
WMessage,
}
接下来就可以愉快的使用了,具体的使用姿势如下
this.$Message({content:'this is info'})
// 不指定 type 默认为 info
this.$Message({type:'info',content:'This is a closed message',closable:true})
// 这种情况就会有关闭的叉叉
this.$Message({type:'info',content:'this is 10-second message',duration:10})
// 时长 10 秒让 message 多待会
this.$Message({type:'info',content:'This is a message that can not be closed',duration:0})
// 时长为 0 表示不想让消失
this.$Message({type:'info',content:'This is a custom closed text message',closeTxt:'朕知道了',duration:10})
// 自定义关闭文字也可以皮一下
至此一个 message 组件就愉快的实现了,可以满足大多数场景的需求,扩展性也是比较 OK 的,可是总觉得还缺点功能,路过的看官伸出无敌的小手指正一下可好?