Vue 中 mixins / extends / component / extend使用

17 篇文章 0 订阅


  • Vue.extend()只是创建一个构造器,为了创建可复用的组件;
  • Vue.component() 创建或者获取组件;
  • mixins,extedns是为了扩展组件;

1,mixins混入

参考mixins混入官方文档和例子

混入 (mixin) :分发 Vue 组件中的可复用功能。一个混入对象可以包含任意组件选项。当组件使用混入对象时,所有混入对象的选项将被“混合”进入该组件本身的选项。

  • 方法和参数在各组件中不共享
  • 值为对象的选项,如methods,components等,选项会被合并,键冲突的组件会覆盖混入对象
  • 值为函数的选项,如created,mounted等,就会被合并调用,混合对象里的钩子函数在组件里的钩子函数之前调用
  • 4、全局混入和局部混入
mixins混入案例—elementUI源码broadcast与dispatch

elementUI源码以局部混入minix的方式引入, 实现多层级分发对应事件的组件间通信: broadcast与dispatch

/src/mixins/emitter.js文件

function broadcast(componentName, eventName, params) {
  this.$children.forEach(child => {
     ... ...
      broadcast.apply(child, [componentName, eventName].concat([params]));
  });
}
export default {
  methods: {
    dispatch(componentName, eventName, params) {
	  ... ...
      if (parent) { parent.$emit.apply(parent, [eventName].concat(params)); }
    },
    broadcast(componentName, eventName, params) {
      broadcast.call(this, componentName, eventName, params);
    }
  }
};

局部混入引进

import Emitter from 'element-ui/src/mixins/emitter';
 export default{
   mixins: [Emitter],
   mounted(){
      this.broadcast('ElDropdownMenu', 'visible', val);
   }
 }

以全局混入minix的方式,分发Action请求使用:this.dispatchAction('getBusinessList', params) ;

Vue.mixin({
  methods: {
    dispatchAction(action, params = {}, plain = false) {
      return new Promise((resolve, reject) => {
        this.$store.dispatch(action, plain ? params : Object.assign({}, params)).then(resp => {
          resolve(resp)
        }).catch(error => {
          reject(error)
        })
      })
    }
  }
})
mixins混入原理

原因:修改Vue.options属性进而影响之后的所有Vue实例。
做法: 将传入的mixin对象与this.options合并,然后将合并后的新对象作为this.options传给之后的所有Vue实例。

Vue.mixin = function (mixin: Object) {
    this.options = mergeOptions(this.options, mixin)
    return this
}


2,extends

  • 与mixins 类似,原理都是mergeOptions实现,组件自身的选项会比要扩展的源组件具有更高的优先级,但是执行顺序:extend > extends > mixins > component

  • 允许声明扩展另一个组件 (可以是一个简单的选项对象或构造函数),而无需使用 Vue.extend;
    mixins接受的是数组:mixins: [Popup, emitter]; extends单继承,只接受一个选项对象或构造函数: extends: baseOptions

var CompA = { ... }
// 在没有调用 `Vue.extend` 时候继承 CompA
var CompB = {
  extends: CompA,
  ...
}


3,component组件

用法: Vue.component(id, [definition])

有第二个参数{Function | Object} [definition] ,则为注册组件,没有则为获取组件

  <div id="itany">
  <hello></hello>
  <my-world></my-world>
 </div>
 <script>
  // 方式1:先创建组件构造器,然后由组件构造器创建组件
  // 使用Vue.extend()创建一个组件构造器
  var MyComponent = Vue.extend({ template: '<h3>Hello World</h3>' });
  // 使用Vue.component(标签名,组件构造器),根据组件构造器来创建组件
  Vue.component('hello', MyComponent);

  //  方式2:直接创建组件(推荐) , 传入一个选项对象 (自动调用 Vue.extend)
  Vue.component('my-world', { template: '<h1>你好,世界</h1>' });
  
  // 在初始化根实例之前注册组件
  var vm = new Vue({ 	//这里的vm也是一个组件,称为根组件Root
   el: '#itany',
   data: {}
  }); 
 </script>

获取注册的组件 (始终返回构造器) : var MyComponent = Vue.component('my-world')

Vue.component() 原理

Vue.component()、Vue.directive()和Vue.filter()的注册方法类似,给指定的一个构造函数与一个字符串ID关联起来。
之后Vue可以把它用作模板,当传递第二个参数definition给Vue.component()的时候,实际上内部调用Vue.extend(),这就是Vue.extend()和Vue.component()的区别。

源码如下:

Vue[type] = function (id,definition) {
   if (!definition) {
      return this.options[type + 's'][id]
   } else {
	  definition = this.options._base.extend(definition)
	  this.options[type + 's'][id] = definition
  }
}


4,extend构造器

<div id="mount-point"></div>

// 创建构造器
var Profile = Vue.extend({
  template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
  data: function () {
    return {
      firstName: 'Walter',
      lastName: 'White',
      alias: 'Heisenberg'
    }
  }
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')

结果: <p>Walter White aka Heisenberg</p>

extend 创建的是 Vue 构造器,而不是我们平时常写的组件实例,所以不可以通过 new Vue({ components: Profile })来直接使用,需要通过 new Profile().$mount('#mount-point')来挂载到指定的元素上,通常组合: Vue.extend + vm.$mount

extend案例—elementUI源码notification

elementUI源码中 loading、message、notification都使用到了Vue.extend()

  • 1,先创建一个组件,也就是弹窗的Dom结构样式以及需要用的数据等;

2-1,再创建一个js文件,引入刚刚创建的组件;
2-2,利用Vue.extend()构造一个子类实例,然后把包装的数据和方法传进去;
2-3,调用$mount()方法生成需要的DOM,然后插入body中,这样就可以通过 $el 属性来访问组件实例

const NotificationConstructor = Vue.extend(Main);
instance = new NotificationConstructor({  data: options });
instance.$mount();
document.body.appendChild(instance.$el);
instance.dom = instance.$el;
instance.dom.style.zIndex = PopupManager.nextZIndex();
  • 3,将第二步的方法挂载到Vue原型上,以保证在项目中可以直接调用:Vue.prototype.$notify = Notification;

  • 4,使用:this.$notify({ title: '提示', message: '这是一条消息' });



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值