vue插件化之.extend基础应用

10 篇文章 0 订阅

1.extend是什么?

首先看文档就能知道它是一个基于Vue构造函数的‘子类’,Vue是一个构造函数,而extend创造出来的也是一个构造函数,只不过.extend是Vue的子构造函数,也就是说.extend继承Vue上的东西,其次.extend是Vue2中的东西,Vue3移除掉了。那它具体是什么?应用于哪些方面呢?请看案例:实现的是一个MessageBox组件==》归属于MyUI组件库。

//构造器:
var Contructor = Vue.extend({
	name: '',
	components: {},
	props: {},
	render: h => h();
})
//so
new Contructor();

如上:他创造的很明显是一个构造器,所以可以通过new获得了一个当前组件的实例(如下案例代码中的messageBox是一个新的应用了,可以使用.$mount()挂载它),称之为子应用的实例,返回一个组件实例(如下案例代码中的this.vm),然后通过原生DOM进行相应的操作。

// MessageBox/index.js
import _MessageBox from './MessageBox.vue'

export default {
  install(vue) { // install开发插件,因为该构造器有vue这个实例,可以使用vue.component和vue.extend,直接use触发调用。
    let messageBox = null;
    // 全局注册组件
    vue.component(_MessageBox.name, _MessageBox);
    // 将方法放到vue实例的原型对象上,注册一个对象用来保存
    vue.prototype.$messageBox = {
      show,
      hide,
      info,
      success,
      warn,
      danger
    }

    //3.实现.info .success .warn .danger四个方法直接使用不同弹框
    function info(props, callback) {
      this.show({...props, type: 'primary'}, callback);
    }

    function success(props, callback) {
      this.show({...props, type: 'success'}, callback);
    }

    function warn(props, callback) {
      this.show({...props, type: 'warn'}, callback);
    }

    function danger(props, callback) {
      this.show({...props, type: 'danger'}, callback);
    }

    function show(props, callback) {
      if(!messageBox){ // 判断是否存在messageBox这个实例,如果不存在则去创造这个实例
        const MessageBox =  vue.extend({
          render(h){
            return h('message-box', { props })
          }
        });
        messageBox = new MessageBox(); // 同main.js中的new vue 构造函数
        this.vm = messageBox.$mount(); // 调用$mount 获取$el
        document.body.appendChild(this.vm.$el);

        // 2.增加回调函数
        callback && callback();
      }
    }

    function hide(callback) {
      document.body.removeChild(this.vm.$el);
      messageBox.$destroy();
      messageBox = null;
      this.vm = null;
      callback && callback();
    }
  }
};

简单说一下render函数中的h:
它返回一个‘虚拟节点’,即h,其中可传入三个参数:type(Html标签名|组件|异步组件|函数式组件),一个对象如props、attribute等。我们通过上面代码中的show(props){}实例传递props。

render() {
	return h('message-box',{},'')
}

如下:是MessageBox组件,但它并不存在与<div id='app'></div>根节点中,而是脱离根节点,存在于body标签中

// MessageBox/MessageBox.vue
<template>
  <div :class="['message-box', type]">
    <div class="inner">
      <header class="header">
        <h1 class="title">{{ title }}</h1>
        <span class="close-btn" @click="hideMessageBox">X</span>
      </header>
      <div class="countent">{{ countent }}</div>
    </div>
  </div>
</template>

<script>
export default {
  name: "MessageBox",
  props: {
    title: {
      type: String,
      default: 'This is Title',
    },
    countent: {
      type: String,
      default: "This is Countent"
    },
    type: {
      type: String,
      default: 'primary',
      validator (value) { // 传入的值必须在这个数组之内
        return [
          'primary',
          'success',
          'warn',
          'danger'
        ].includes(value);
      }
    }
  },

  methods: {
    hideMessageBox() {
      this.$messageBox.hide(()=>{
        console.log('Hide')
      })
    }
  }

}
</script>

<style lang="scss">
body {
  margin: 0;
}

h1 {
  margin: 0;
  font-weight: normal;
}

.message-box {
  position: fixed;
  top: 0;
  left: 0;
  height: 100%;
  width: 100%;
  background-color: rgba(0,0,0,.5);

  .inner {
    position: absolute;
    top: 100px;
    left: 50%;
    width: 500px;
    margin-left: -250px;
    background-color: #fff;
    box-shadow: 1px 3px 5px #ededed;
    border-radius: 5px;
    overflow: hidden;

    .header {
      height: 44px;
      padding: 0 10px;
      line-height: 44px;
      box-sizing: border-box;

      .title {
        float: left;
        font-size: 16px;
      }

      .close-btn {
        float: right;
        cursor: pointer;
      }

    }
    .countent{
      padding: 20px;
      box-sizing: border-box;
    }
  }

  &.primary {
    header {
      background-color: blue;
      color: #fff;
    }
  }
  &.success {
    header {
      background-color: green;
      color: #fff;
    }
  }
  &.warn {
    header {
      background-color: orange;
      color: #333;
    }
  }
  &.danger {
    header {
      background-color: red;
      color: #fff;
    }
  }
}
</style>

最后在MyUI组件库中导出:

// components/MyUI/index.js
import MessageBox from './MessageBox'

export  {
  MessageBox
};

在main.js中引入

import { MessageBox } from './components/MyUI'

Vue.use(MessageBox);

在vue组件使用

<template>
  <div>
    <button @click="openMessageBox">show</button>
  </div>
</template>

<script>
export default {
  name: "App",
  methods: {
    openMessageBox() {
      this.$messageBox.show({
        title: 'App',
        countent: 'This is Countent for App',
        type: "success"
      }, ()=> {
        console.log('Open')
      });
    }
  }
 }
</script>

<style>

</style>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值