vue插件基本雏形
vue基本知识
//main.js中引入和使用插件
import toast from './components/toast';
Vue.use(toast)
//./components/toast/index.js
const obj = {};
obj.install = function(Vue){
console.log(Vue);
}
export default obj;
Vue的use方法会自动调用引入对象的install方法,并将Vue传入到install方法中,即会打印出Vue的构造函数
vue绑定对象问题
./components/toast/index.js引入toast.vue模板
import Toast from './toast.vue';
const obj = {};
obj.install = function(Vue){
console.log(Vue);
console.log(Toast.$el);
Vue.prototype.$toast = Toast;
}
export default obj;
在其他模板中虽然能打印出this.$toast 但是没办法将template里面的html代码插入到body中,Toast.$el为undefined是因为没有挂在到dom节点上
import Toast from './toast.vue';
const obj = {};
obj.install = function(Vue){
// 1.创建组件构造器
const ToastConstructor = Vue.extend(Toast);
// 2.new方式生成组件对象
const ToastObj = new ToastConstructor();
console.log(ToastObj);
// 3.将组件对象挂在到某个div上
ToastObj.$mount(document.createElement('div'));
console.log(ToastObj.$el);
// 4.将组件添加到body中
document.body.appendChild(ToastObj.$el);
Vue.prototype.$toast = ToastObj;
}
export default obj;
toast.vue文件
<template>
<div class="toast" v-show="isShow">
{{message}}
</div>
</template>
<script>
export default {
name: 'toast',
props:{
/*message:{
type:String,
default:'默认提示'
},
duration:{
type:Number,
default:2000
}*/
},
data() {
return {
message:'',
isShow: false
}
},
methods:{
show(message,duration=2000) {
this.isShow = true;
this.message = message;
setTimeout(()=>{
this.message= '';
this.isShow = false;
},duration)
}
}
}
</script>
<style scoped>
.toast {
position: fixed;
z-index:999;
background-color: red;
top:50%;
left: 50%;
transform: translate(-50%,-50%);
padding: 8px 10px;
background-color: rgba(0,0,0,.75);
color: #fff;
}
</style>
这种方式虽然能实现功能,但是使用的时候用this.$toast.show(‘haha’,10000)这种方式默认调用里面的方法,不太好。 下面改造成this.$toast({message:‘haha’,duration:5000})这种对象使用方法。
import Vue from 'vue';
import Toast from './toast.vue';
export const messageBox = (function(){
//默认配置
const defaults ={
title:'',
content:'',
cancel:'取消',
ok:'确认',
handleCancel:null,
handleOk:null
};
const MyComponent = Vue.extend(Toast);
return function(opts){
for(let attr in opts){
defaults[attr]=opts[attr];
}
//const MyComponent = Vue.extend(Toast);
const vm = new MyComponent({
el:document.createElement('div'),
data:{
title:defaults.title,
content:defaults.content,
cancel:defaults.cancel,
ok:defaults.ok
},
methods:{
handleCancel(){
defaults.handleCancel && defaults.handleCancel.apply(this);
document.body.removeChild(vm.$el);
},
handleOk(){
defaults.handleOk && defaults.handleOk.apply(this);
document.body.removeChild(vm.$el);
}
}
});
document.body.appendChild(vm.$el)
}
})();
<template>
<div class="messageBox">
<h2>{{title}}</h2>
<p>{{content}}</p>
<div>
<div @click="handleCancel">{{cancel}}</div>
<div @click="handleOk">{{ok}}</div>
</div>
</div>
</template>
<script>
export default {
name: 'messageBox',
data() {
return {}
}
}
</script>
<style scoped>
*{
margin: 0;
padding: 0;
}
.messageBox {
position: fixed;
width: 200px;
/*height: 110px;*/
border: 1px solid #ccc;
top:50%;
left: 50%;
transform: translate(-50%,-50%);
background-color: rgba(0,0,0,.75);
color: #fff;
}
.messageBox h2{
text-align: center;
line-height: 40px;
font-size: 18px;
}
.messageBox p{
text-align: center;
line-height: 40px;
}
.messageBox > div{
position: relative;
display: flex;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 30px;
border-top: 1px solid #ccc;
}
.messageBox > div div{
flex:1;
text-align: center;
line-height: 30px;
border-right: 1px solid #ccc;
}
.messageBox > div div:last-child{
border: none;
}
</style>
使用方式:
- 先引入改插件
import { messageBox } from ‘…/components/toast1’ - 在使用 showToast为使用组件内部方法
showMessage(){
let that = this;
messageBox({
title:'沈阳',
content:'内容阿萨德发挥擦搜ID发财树六还不阿斯顿发的发多岁的',
cancel:'去下',
ok:'城市定位',
handleOk(){
that.showTitle();
},
handleCancel() {
console.log(this); //指向messageBox组件
that.showToast('你好啊',5000);
that.showTitle();
}
})
}
messageBox的另一版
index.js文件
import Vue from 'vue';
import Toast from './messageBox.vue';
const obj = {};
obj.install = function(Vue,opts){
const MyComponent = Vue.extend(Toast);
Vue.prototype.$messageBox = function(opts){
//默认配置
const defaults ={
title:'标题',
content:'内容',
cancel:'取消',
ok:'确认',
handleCancel:null,
handleOk:null
};
for(let attr in opts){
defaults[attr]=opts[attr];
}
const vm = new MyComponent({
el:document.createElement('div'),
data:{
title:defaults.title,
content:defaults.content,
cancel:defaults.cancel,
ok:defaults.ok
},
methods:{
handleCancel(){
defaults.handleCancel && defaults.handleCancel.apply(this);
document.body.removeChild(vm.$el);
},
handleOk(){
defaults.handleOk && defaults.handleOk.apply(this);
document.body.removeChild(vm.$el);
}
}
});
document.body.appendChild(vm.$el)
}
}
export default obj;
messageBox.vue文件
<template>
<div class="toast2">
<h2>{{title}}</h2>
<p>{{content}}</p>
<div>
<div @click="handleCancel">{{cancel}}</div>
<div @click="handleOk">{{ok}}</div>
</div>
</div>
</template>
<script>
export default {
name: 'toast2',
data() {
return {}
}
}
</script>
<style scoped>
.toast2 {
position: fixed;
width: 200px;
border: 1px solid #ccc;
top:50%;
left: 50%;
transform: translate(-50%,-50%);
background-color: rgba(0,0,0,.75);
color: #fff;
}
.toast2 h2{
text-align: center;
line-height: 40px;
font-size: 18px;
}
.toast2 p{
text-align: center;
line-height: 40px;
}
.toast2 > div{
position: relative;
display: flex;
bottom: 0;
left: 0;
right: 0;
width: 100%;
height: 30px;
border-top: 1px solid #ccc;
}
.toast2 > div div{
flex:1;
text-align: center;
line-height: 30px;
border-right: 1px solid #ccc;
}
.toast2 > div div:last-child{
border: none;
}
</style>
使用:在main.js中引入并安装
import messageBox from ‘./components/toast2’
Vue.use(messageBox);
在用的组件上
showMes(){
const that = this;
this.$messageBox({
title:'messageBoxTitle',
content:'messageBoxContent',
ok:'box确认',
cancel:'box取消',
handleCancel(){
console.log(this); //指向messageBox组件
that.showToast('你好啊',5000);
that.showTitle();
},
handleOk() {
that.showTitle();
}
})
}
还剩问题是别人组件没有const that = this 的this指向问题直接使用内部的方法