Vue3:探讨一下mixin
Posted 你吃香蕉吗?
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue3:探讨一下mixin相关的知识,希望对你有一定的参考价值。
一、Vue2中的mixin
1、定义要混入的数据对象
// 定义一个 mixin 对象
export const myMixin =
created()
this.hello()
,
methods:
hello()
console.log('hello from mixin!')
2、在需要这些东西的地方去通过mixins获得mixin对象
<template>
<div>
<h1>我是页面1</h1>
<h2>hello: hello </h2>
</div>
</template>
<script>
import myMixin from '@/mixin/test1.js'
export default
mixins: [myMixin],
</script>
<style></style>
3、解决的问题(说作用可能更准确点)
vue2.x中,mixin是将部分组件逻辑抽象成可重用块的工具,也就是重要的“复用”
4、存在的问题
mixin很容易发生冲突:因为mixin中的property都被合并到了一个组件中,同名的会被覆盖,需要了解每一个选项默认的合并特性
数据来源不明确:如果你引入了多个mixin对象,那你想要知道其中一个具体方法、属性等的来源无疑是很难查找的
可重用性有限:我们只能被动的使用mixin中传递的任何东西,而不能通过参数传递的方式来改变其中的某些逻辑,这大大降低了它抽象逻辑方面的灵活性
5、vue2中mixin详解
请参考:Vue混入mixin_你吃香蕉吗?的博客-CSDN博客
二、Vue3中有mixin吗?需要mixin吗?
1、结论:vue3中没有mixin,也不需要mixin
2、vue3中没有mixin?
如果大家在这之前看过vue3的官方文档,那么大家就会发现,在vue3的文档中提到mixin的地方极少无比,所能找到的地方也只是在说vue2的一些写法之类的,那既然没写mixin,大概率就在vue3中没有mixin了,接下来我们会肯定它没有mixin。
官方很重要的一段话:为了解决Vue2存在的问题,我们添加了一种通过逻辑关注点组织代码的新方法:组合式 API。
3、vue3不需要mixin?
vue3相比较vue2来说,它更加的接近函数式编程,说白了就是写js,用写js的方式方法来写页面
提到这里我想大家应该能够想到一个关键词:公共
而上面所说也就是组合式API——Composition API
在Composition API中,我们可以抽离出每一个逻辑点为单独的js文件,再通过import的方式去把页面的所有内容组合在一起,实现一个完整的页面。
同样的,如果多个页面、组件,用到的方法、变量都是同样的,那么我们可以把这一个js文件同时引入到多个文件中,然后再进行使用,这也就达到了mixin的效果,甚至我们可以通过接受参数的方式对公共的方法作出定制化处理
三、Vue3中“Mixin”的实践
1、目录结构
2、index.vue
<template>
<A></A>
<B></B>
</template>
<script setup lang="ts">
import A from './A.vue'
import B from './B.vue'
</script>
3、homeMixin.ts
export default function getHomeMixin(source: string)
let name = ref<string>('张三');
const componentName = source
const handleChangeName = (transmitName: string) =>
name.value = transmitName
return
name,
componentName,
handleChangeName
4、A、B组件
A组件
<template>
<div class="A">
<p>A组件</p>
<p>minxin: Mixin.name </p>
<p> Mixin.componentName </p>
<el-button @click="Mixin.handleChangeName('法外狂徒-张三')">A组件改变mixin中得到的数据</el-button>
</div>
</template>
<script setup lang="ts">
import getHomeMixin from './homeMixin'
const Mixin = getHomeMixin('我是A组件传的值');
</script>
<style lang="less" scoped>
.A
width: 300px;
height: 300px;
background-color: aquamarine;
</style>
B组件
<template>
<div class="B">
<p>B组件</p>
<p>minxin: Mixin.name </p>
<p> Mixin.componentName </p>
<el-button @click="Mixin.handleChangeName('尼古拉斯-赵四')">B组件改变mixin中得到的数据</el-button>
</div>
</template>
<script setup lang="ts">
import getHomeMixin from './homeMixin'
const Mixin = getHomeMixin('我是B组件传的值');
</script>
<style lang="less" scoped>
.B
width: 300px;
height: 300px;
background-color: burlywood;
</style>
5、效果
Vue.mixin Vue.extend(Vue.component)的原理与区别
1.本文将讲述 方法 Vue.extend Vue.mixin 与 new Vue({mixins:[], extend:{}})的区别与原理
先回顾一下 Vue.mixin 官网如下描述:
Vue.mixin( mixin )全局注册一个混入,影响注册之后所有创建的每个 Vue 实例。插件作者可以使用混入,向组件注入自定义的行为。
既然可以影响到注册后的所有实例,那么该方法注入的方法和属性都存放在哪里呢(构造函数的options属性上),我们一起来看看该方法的定义
Vue.mixin = function (mixin) {
//mergeOption,将Vue构造函数的Options属性与传入的mixin参数进行合并,
//合并之后再复制给Vue构造函数的Options属性
this.options = mergeOptions(this.options, mixin);
return this
};
为什么Vue.mixin方法将mixin合并至Vue.options就能影响注册之后的所有实例呢,让我们看看Vue实例化的过程(将构造函数的options属性与实例化参数合并后付给实例的$options属性
)
1 function Vue(options) { 2 //调用_init方法 3 this._init(options); 4 } 5 6 7 8 Vue.prototype._init = function (options) { 9 var vm = this; 10 // a uid 11 vm._uid = uid$3++; 12 13 var startTag, endTag; 14 21 // a flag to avoid this being observed 标记该对象是一个Vue实例 22 vm._isVue = true; 23 // merge options 24 if (options && options._isComponent) { //组件实例化过程,即Vue.extend返回对象--稍后解释 25 // optimize internal component instantiation 26 // since dynamic options merging is pretty slow, and none of the 27 // internal component options needs special treatment. 28 initInternalComponent(vm, options); 29 } else {//将构造函数的options属性与实例化参数合并后付给实例的$options属性 ,该属性会在函数initState中进行初始化 30 vm.$options = mergeOptions( 31 resolveConstructorOptions(vm.constructor), 32 options || {}, 33 vm 34 ); 35 } 36 /* istanbul ignore else */ 37 { 38 initProxy(vm); 39 } 40 // expose real self 41 vm._self = vm; 42 initLifecycle(vm); 43 initEvents(vm); 44 initRender(vm); 45 callHook(vm, ‘beforeCreate‘); 46 initInjections(vm); // resolve injections before data/props 47 initState(vm); 48 initProvide(vm); // resolve provide after data/props 49 callHook(vm, ‘created‘); 50 51 /* istanbul ignore if */ 52 if ("development" !== ‘production‘ && config.performance && mark) { 53 vm._name = formatComponentName(vm, false); 54 mark(endTag); 55 measure(("vue " + (vm._name) + " init"), startTag, endTag); 56 } 57 58 if (vm.$options.el) { 59 vm.$mount(vm.$options.el); 60 } 61 };
Vue.extend-- 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象
该方法返回一个与Vue具有相同功能的构造函数(其实为创建了一个组件)-属性options是 合并 基础 Vue 构造器 与 extend的参数 的对象,
Vue.extend = function (extendOptions) { extendOptions = extendOptions || {}; //将调用函数付给Super var Super = this; var SuperId = Super.cid; //如果参数中参入与创建的构造函数则直接返回 var cachedCtors = extendOptions._Ctor || (extendOptions._Ctor = {}); if (cachedCtors[SuperId]) { return cachedCtors[SuperId] } //获取组件的名称 var name = extendOptions.name || Super.options.name; if ("development" !== ‘production‘ && name) { validateComponentName(name); } //创建组件Sub var Sub = function VueComponent(options) { this._init(options); };
//为组件添加对应的属性与方法 Sub.prototype = Object.create(Super.prototype); Sub.prototype.constructor = Sub; Sub.cid = cid++;
//合并super的options与extend的入参并赋值给Sub的options属性 Sub.options = mergeOptions( Super.options, extendOptions );
//在sub上保存Super的信息 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$1(Sub); } if (Sub.options.computed) { initComputed$1(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
//如果有组件名称,将该组件挂载到sub.options.components上。以便可在组件内使用
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.
//保存option信息。以便在render的时候生成最新的options选项
Sub.superOptions = Super.options; Sub.extendOptions = extendOptions; Sub.sealedOptions = extend({}, Sub.options); // cache constructor cachedCtors[SuperId] = Sub; return Sub //返回sub构造函数 };
Vue.component
以上是关于Vue3:探讨一下mixin的主要内容,如果未能解决你的问题,请参考以下文章