vue插件

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>

使用方式:

  1. 先引入改插件
    import { messageBox } from ‘…/components/toast1’
  2. 在使用 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指向问题直接使用内部的方法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值