vue自定义插件的方法

一、定义插件的目的是为了使用函数式调用某个全局组件,方便直接在js中调用,
不需要在任何组件中声明,大概是这样的效果

this.$toast({
            title: '我是toast',
            closeButton: {
                text: '知道了',
                callback () {
                    console.log('用户说他知道了');
                }
            }
       })

 二、实现过程:
1.准备好需要的组件

<template>
  <div>
    <div>{{title}}</div>
    <!-- <slot></slot> -->
  </div>
</template>
<script>
export default {
  data() {
    return {};
  },
  props: {
    title: {
        type: String,
        default: ''
    },
    closeButton: {
        type: Object,
        default () {
            return {
                text: '关闭',
                callback: undefined
            }
        }
    }
  },
  methods: {
    close() {
      // 删除组件方法,将真实的dom节点删掉
      this.$el.remove();
      // 将虚拟节点占的内存也释放掉
      this.$destroy();
    },
    onClickClose () {
        this.close();
        if (this.closeButton && typeof this.closeButton.callback === 'function') {
           this.closeButton.callback(this) // this === toast实例
        }
    }
  },
};
</script>

这里:如果我们想在js调用组件的时候,拿到组件实例,并调用组件里的方法,可以把this传出去, this === toast实例,然后在调用的地方这样使用:

this.$toast({
            title: '我是toast',
            closeButton: {
                text: '知道了',
                callback (toast) {
                    toast.log() //调用组件内部方法
                    console.log('用户说他知道了');
                }
            }
       })
  1. 将组件实例化,并转化成真实dom
    这里:Vue.extend()其实就是用来创建组件的构造函数的,然后使用这个构造函数创建出Vue的虚拟节点Vnode

 

import Toast from './demoPage'
export default {
    install(Vue, options) {
        Vue.prototype.$toast = function (options) {
            // 1.使用Vue.extend创建构造函数,MyComponent是自定义的vue组件(MyComponent.vue)
            let Constructor = Vue.exend(Toast)
            // 构造函数的参数,propsData相当于我们组件MyComponent.vue里需要的props,
            // 这里为了和vue文件中的props冲突,所以官方取了个别名 
            // 2.然后实例化后,会生成一个vue组件对应的虚拟节点
            let toast = new Constructor({
                propsData: options
            })
            // toast.$slot.default = [options.message]
            // 3.将vm转化成真实dom
            toast.$mount();
            // 4.将真实dom,挂载到body上
            document.body.appendChild(toast.$el)
        }
    }
}

 进一步可以封装成:

import Toast from './demoPage';
function createToast({ Vue, propsData }) {
    // 1.使用Vue.extend创建构造函数,MyComponent是自定义的vue组件(MyComponent.vue)
    let Constructor = Vue.exend(Toast)
    // 构造函数的参数,propsData相当于我们组件MyComponent.vue里需要的props,
    // 这里为了和vue文件中的props冲突,所以官方取了个别名 
    // 2.然后实例化后,会生成一个vue组件对应的虚拟节点
    let toast = new Constructor({
        propsData
    })
    // toast.$slot.default = [propsData.message]
    // 3.将vm转化成真实dom
    toast.$mount();
    // 4.将真实dom,挂载到body上
    document.body.appendChild(toast.$el)
}


export default {
    install(Vue, options) {
        Vue.prototype.$toast = funtion(options) {
            createToast({ Vue, propsData: options })
        }
    }
}

优化,避免创建多次:

mport Toast from './demoPage';
function createToast({ Vue, propsData }) {
    // 1.使用Vue.extend创建构造函数,MyComponent是自定义的vue组件(MyComponent.vue)
    let Constructor = Vue.exend(Toast)
    // 构造函数的参数,propsData相当于我们组件MyComponent.vue里需要的props,
    // 这里为了和vue文件中的props冲突,所以官方取了个别名 
    // 2.然后实例化后,会生成一个vue组件对应的虚拟节点
    let toast = new Constructor({
        propsData
    })
    // toast.$slot.default = [propsData.message]
    // 3.将vm转化成真实dom
    toast.$mount();
    // 4.将真实dom,挂载到body上
    document.body.appendChild(toast.$el)
}

let currentToast;
export default {
    install(Vue, options) {
        Vue.prototype.$toast = funtion(options) {
            if (currentToast) {
                currentToast.close()
            }
            currentToast = createToast({ Vue, propsData: options })
        }
    }
}

 继续优化:

 methods: {
    close() {
      // 删除组件方法,将真实的dom节点删掉
      this.$el.remove();
      this.$emit('close')
      // 将虚拟节点占的内存也释放掉
      this.$destroy();
    }
  },
import Toast from './demoPage';
function createToast({ Vue, propsData, onClose }) {
    // 1.使用Vue.extend创建构造函数,MyComponent是自定义的vue组件(MyComponent.vue)
    let Constructor = Vue.exend(Toast)
    // 构造函数的参数,propsData相当于我们组件MyComponent.vue里需要的props,
    // 这里为了和vue文件中的props冲突,所以官方取了个别名 
    // 2.然后实例化后,会生成一个vue组件对应的虚拟节点
    let toast = new Constructor({
        propsData
    })
    // toast.$slot.default = [propsData.message]
    // 3.将vm转化成真实dom
    toast.$mount();
    toast.$on('close', onClose)
    // 4.将真实dom,挂载到body上
    document.body.appendChild(toast.$el)
}
let currentToast

export default {
    install(Vue, options) {
        Vue.prototype.$toast = funtion(options) {
            if (currentToast) {
                currentToast.close()
            }
            currentToast = createToast({
                Vue, propsData: options, onClose: () => {
                    currentToast = null
                }
            })
        }
    }
}

3.在入口文件main.js中调用插件:

// 导入插件
import noticePlugin from '@/notice/index'
// 使用插件
Vue.use(noticePlugin)

 

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值