vue.extend 简单讲解

2,481 阅读1分钟

Vue.extend 是 vue的全局API,在平常业务开发过程中,使用的频率不高。在一些独立的开发场景中,我们常常将 Vue.extend 和 $mount 就行结合使用。

一、基本使用

  • Vue.extend( options )
  • 参数: {Object} options 用法:

使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

data 选项是特例,需要注意 - 在 Vue.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>

注意: Vue.extend创建的是一个构造器,和我们平常用的组件区别还是比较大的。注意是使用 new Profile().$mount('#mount-point') 进行指定元素的挂载,而不是 new Vue()

二、Vue.extend 和 Vue.component 的区别

  1. Vue.component 需要进行组件注册才能使用,在 template中使用注册的标签名来使用;Vue.extend 是编程式写法
  2. 关于组件的显示与否,需要在父组件中传入一个状态来控制 或者 在组件外部用 v-if/v-show 来实现控制;而 Vue.extend 的显示与否是手动的去做组件的挂载和销毁。
  3. Vue.component 使用起来更为简单,Vue.extend 常用来封装一些全局组件。

三、Vue.extend 的应用

element-ui框架中message 和 message-box 等全局组件的实现,便使用了 Vue.extend。 以message组件为例进行详细分析。

1. 创建 main.vue 组件

创建message组件的架子,这里支持多种类型的信息提醒,使用变量 typeClass 和 type 来控制。

<template>
  <transition name="el-message-fade" @after-leave="handleAfterLeave">
    <div
      :class="[
        'el-message',
        type && !iconClass ? `el-message--${ type }` : '',
        center ? 'is-center' : '',
        showClose ? 'is-closable' : '',
        customClass
      ]"
      :style="positionStyle"
      v-show="visible"
      @mouseenter="clearTimer"
      @mouseleave="startTimer"
      role="alert">
      <i :class="iconClass" v-if="iconClass"></i>
      <i :class="typeClass" v-else></i>
      <slot>
        <p v-if="!dangerouslyUseHTMLString" class="el-message__content">{{ message }}</p>
        <p v-else v-html="message" class="el-message__content"></p>
      </slot>
      <i v-if="showClose" class="el-message__closeBtn el-icon-close" @click="close"></i>
    </div>
  </transition>
</template>

2. vue.extend 实现

  • let MessageConstructor = Vue.extend(Main): 将main组件引入创建构造器
  • 声明一个 Message 对象,内部将 MessageConstructor 实例化并进行挂载: instance.$mount()
let MessageConstructor = Vue.extend(Main);

const Message = function(options) {
  if (Vue.prototype.$isServer) return;
  options = options || {};
  if (typeof options === 'string') {
    options = {
      message: options
    };
  }
  let userOnClose = options.onClose;
  let id = 'message_' + seed++;

  options.onClose = function() {
    Message.close(id, userOnClose);
  };
  instance = new MessageConstructor({
    data: options
  });
  instance.id = id;
  if (isVNode(instance.message)) {
    instance.$slots.default = [instance.message];
    instance.message = null;
  }
  instance.$mount();
  document.body.appendChild(instance.$el);
  let verticalOffset = options.offset || 20;
  instances.forEach(item => {
    verticalOffset += item.$el.offsetHeight + 16;
  });
  instance.verticalOffset = verticalOffset;
  instance.visible = true;
  instance.$el.style.zIndex = PopupManager.nextZIndex();
  instances.push(instance);
  return instance;
};

['success', 'warning', 'info', 'error'].forEach(type => {
  Message[type] = options => {
    if (typeof options === 'string') {
      options = {
        message: options
      };
    }
    options.type = type;
    return Message(options);
  };
});

四、总结

vue是单页面框架,不同页面都是通过router进行控制组件的显示与否。Vue.component 注册的组件都是在当前位置渲染,但若我们想在JavaScript中使用alert()一样方便去使用组件,就可以结合 Vue.extend + $mount 来实现