深入浅析Vue中mixin和extend的区别和使用场景


Posted in Javascript onAugust 01, 2019

Vue中有两个较为高级的静态方法mixin和extend,接下来我们来讨论下关于他们各自的原理和使用场景。

Mixin:

原理:

先来看看官网的介绍:

参数:{Object} mixin

用法:

混入也可以进行全局注册。使用时格外小心!一旦使用全局混入,它将影响每一个之后创建的 Vue 实例。使用恰当时,这可以用来为自定义选项注入处理逻辑。

// 为自定义的选项 'myOption' 注入一个处理器。
   Vue.mixin({
    created: function () {
     var myOption = this.$options.myOption
     if (myOption) {
      console.log(myOption)
     }
    }
   })
   
   new Vue({
    myOption: 'hello!'
   })
   // => "hello!"

我们知道,Vue.mixin传递的这个参数对象,在初始化Vue实例的时候会merge到options上,下面是Vue源码中对mixin的操作。

// src\core\global-api\mixin.js
 export function initMixin (Vue: GlobalAPI) {
  Vue.mixin = function (mixin: Object) {
   this.options = mergeOptions(this.options, mixin)
   return this
  }
 }
// src\core\instance\index.js
 function Vue (options) {
   if (process.env.NODE_ENV !== 'production' &&
   !(this instanceof Vue)
   ) {
   warn('Vue is a constructor and should be called with the `new` keyword')
   }
   this._init(options)
 }
 
 initMixin(Vue)
 ...
 
 export default Vue

也就是说,mixin只是对我们在初始化Vue实例时传递的配置对象的一个扩展。

就像上面官网实例写的例子,我们在执行Vue.mixin方法时传递一个配置对象进去,对象里面有个created勾子函数,通过源码我们可以看到这个传递进来的对象最终会和我们在初始化实例也就是new Vue(options)时的这个options合并(通过上面源码中的mergeOptions方法),保存在option上。

使用场景:

当我们需要全局去注入一些methods,filter或者hooks时我们就可以使用mixin来做。 比如我们希望每一个Vue实例都有一个print方法,我们就可以这么做:

Vue.mixin({
    methods: {
      print() {
        console.log(`我是一个通过mixin注入的方法!`)
      }
    }
  })

或者我们想要去监听在什么阶段时什么组件被加载了,被卸载了等等,我们可以这么做:

Vue.mixin({
    mounted() {
      console.log(`${this.$route.name} component mounted!`)
    },
    destroyed() {
      console.log(`${this.$route.name} component destroyed!`)
    }
  })

如果我们并不想给每一个组件实例都混入这些配置options,而只是个别的组件,最好不要使用mixin,它可能会影响到我们组件的性能。

Extend:

原理:

先来看看官网的介绍:

参数:{Object} options

用法:

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

data 选项是特例,需要注意 - 在 Vue.extend() 中它必须是函数。

data必须是函数是为了防止各个实例的数据混乱,闭包的应用。

<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')

再来看看源码里面关于Vue.extend的实现:

Vue.extend = function (extendOptions: Object): Function {
  extendOptions = extendOptions || {}
  const Super = this
  const SuperId = Super.cid
  const cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {})
  if (cachedCtors[SuperId]) {
   return cachedCtors[SuperId]
  }

  const name = extendOptions.name || Super.options.name
  if (process.env.NODE_ENV !== 'production' && name) {
   validateComponentName(name)
  }

  const Sub = function VueComponent (options) {
   this._init(options)
  }
  Sub.prototype = Object.create(Super.prototype)
  Sub.prototype.constructor = Sub
  Sub.cid = cid++
  Sub.options = mergeOptions(
   Super.options,
   extendOptions
  )
  Sub['super'] = Super

  // For props and computed properties, we define the proxy getters on
  // the Vue instances at extension time, on the extended prototype. This
  // avoids Object.defineProperty calls for each instance created.
  if (Sub.options.props) {
   initProps(Sub)
  }
  if (Sub.options.computed) {
   initComputed(Sub)
  }

  // allow further extension/mixin/plugin usage
  Sub.extend = Super.extend
  Sub.mixin = Super.mixin
  Sub.use = Super.use

  // create asset registers, so extended classes
  // can have their private assets too.
  ASSET_TYPES.forEach(function (type) {
   Sub[type] = Super[type]
  })
  // enable recursive self-lookup
  if (name) {
   Sub.options.components[name] = Sub
  }

  // keep a reference to the super options at extension time.
  // later at instantiation we can check if Super's options have
  // been updated.
  Sub.superOptions = Super.options
  Sub.extendOptions = extendOptions
  Sub.sealedOptions = extend({}, Sub.options)

  // cache constructor
  cachedCtors[SuperId] = Sub
  return Sub
 }
}

首先我们可以看到,extend方法返回的Sub其实是一个构造函数,而且继承自Vue,也就是说extend方法返回的是Vue的一个子类。

Sub.prototype = Object.create(Super.prototype)
  Sub.prototype.constructor = Sub

这两行代码其实就是实现Sub对Vue的继承,源码中有一行是

const Super = this

所以这里的Super指的就是Vue。

Sub.options = mergeOptions(
   Super.options,
   extendOptions
)

我们注意到在extend中也会对传进来的配置option和Vue原来的options做一个合并。

使用场景:

当我们不需要全局去混入一些配置,比如,我们想要获得一个component。我们可以使用Vue.component(),也可以使用Vue.extend()。

const ChildVue = Vue.extend({
  ...options
})

new ChildVue({
  ...options
})

注意extend得到的是一个Vue的子类,也就是构造函数。

区别:

mixin是对Vue类的options进行混入。所有Vue的实例对象都会具备混入进来的配置行为。

extend是产生一个继承自Vue类的子类,只会影响这个子类的实例对象,不会对Vue类本身以及Vue类的实例对象产生影响。

总结

以上所述是小编给大家介绍的Vue中mixin和extend的区别和使用场景,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Javascript 相关文章推荐
jQuery建立一个按字母顺序排列的友好页面索引(兼容IE6/7/8)
Feb 26 Javascript
基于JavaScript实现 获取鼠标点击位置坐标的方法
Apr 12 Javascript
探讨在JQuery和Js中,如何让ajax执行完后再继续往下执行
Jul 09 Javascript
js和jquery使按钮失效为不可用状态的方法
Jan 26 Javascript
JavaScript实现把rgb颜色转换成16进制颜色的方法
Jun 01 Javascript
关于JavaScript 原型链的一点个人理解
Jul 31 Javascript
jquery点赞功能实现代码 点个赞吧!
May 29 jQuery
Angularjs的键盘事件的绑定
Jul 27 Javascript
React Native 真机断点调试+跨域资源加载出错问题的解决方法
Jan 18 Javascript
解决vue打包项目后刷新404的问题
Mar 06 Javascript
微信小程序API—获取定位的详解
Apr 30 Javascript
原生js实现的金山打字小游戏(实例代码详解)
Mar 16 Javascript
在Vue环境下利用worker运行interval计时器的步骤
Aug 01 #Javascript
详解Vue2.5+迁移至Typescript指南
Aug 01 #Javascript
微信小程序组件传值图示过程详解
Jul 31 #Javascript
vue.js实现回到顶部动画效果
Jul 31 #Javascript
vue实现滑动超出指定距离回顶部功能
Jul 31 #Javascript
Vue实现回到顶部和底部动画效果
Jul 31 #Javascript
详解mpvue实现对苹果X安全区域的适配
Jul 31 #Javascript
You might like
PHP性能优化工具篇Benchmark类调试执行时间
2011/12/06 PHP
PHP MySql增删改查的简单实例
2016/06/21 PHP
form中限制文本字节数js代码
2007/06/10 Javascript
JQuery 插件模板 制作jquery插件的朋友可以参考下
2010/03/17 Javascript
读jQuery之十三 添加事件和删除事件的核心方法
2011/08/23 Javascript
js获取指定日期前后的日期代码
2013/08/20 Javascript
form.submit()不能提交表单的错误原因及解决方法
2014/10/13 Javascript
学习JavaScript设计模式(多态)
2015/11/25 Javascript
浅谈Web页面向后台提交数据的方式和选择
2016/09/23 Javascript
JS实现PC手机端和嵌入式滑动拼图验证码三种效果
2017/02/15 Javascript
Angular模版驱动表单的使用总结
2018/05/05 Javascript
解决linux下node.js全局模块找不到的问题
2018/05/15 Javascript
vue translate peoject实现在线翻译功能【新手必看】
2018/06/07 Javascript
React 组件渲染和更新的实现代码示例
2019/02/21 Javascript
在vue中使用vuex,修改state的值示例
2019/11/08 Javascript
jquery css实现流程进度条
2020/03/26 jQuery
JS常见错误(Error)及处理方案详解
2020/07/02 Javascript
[01:06:25]Secret vs Liquid 2018国际邀请赛淘汰赛BO3 第一场 8.25
2018/08/29 DOTA
解决python2.7 查询mysql时出现中文乱码
2016/10/09 Python
Python排序搜索基本算法之堆排序实例详解
2017/12/08 Python
Python将DataFrame的某一列作为index的方法
2018/04/08 Python
利用python的socket发送http(s)请求方法示例
2018/05/07 Python
PyQt打开保存对话框的方法和使用详解
2019/02/27 Python
Python-while 计算100以内奇数和的方法
2019/06/11 Python
python3爬取torrent种子链接实例
2020/01/16 Python
使用Pycharm在运行过程中,查看每个变量的操作(show variables)
2020/06/08 Python
Feelunique德国官方网站:欧洲最大的在线美容零售商
2019/07/20 全球购物
交通安全演讲稿
2014/01/07 职场文书
大型营销活动计划书
2014/04/28 职场文书
党的群众路线教育实践活动领导班子整改措施
2014/10/28 职场文书
2015教师节师德演讲稿
2015/03/19 职场文书
《青山不老》教学反思
2016/02/22 职场文书
3招让你摆脱即兴讲话冷场尴尬
2019/08/08 职场文书
高一作文之暖冬
2019/11/09 职场文书
业余无线电通联Q语
2022/02/18 无线电
SQL Server中的逻辑函数介绍
2022/05/25 SQL Server