对Vue中mixin的理解

在UE(用户体验)设计中,Mixin(混入)是一种设计模式和方法,用于实现代码的复用和功能的扩展。Mixin 的基本概念是将一个或多个已定义的功能集合(例如方法、样式、状态等)注入到一个对象或组件中,以增强其功能而无需改变其原有结构。

一、mixin是什么

Mixin是面向对象程序设计语言中的类,提供了方法的实现。其他类可以访问mixin类的方法而不必成为其子类。

Mixin类通常作为功能模块使用,在需要该功能时“混入”,有利于代码复用又避免了多继承的复杂。

Vue中的mixin

看一下官方定义:

mixin(混入),提供了一种非常灵活的方式,来分发 Vue 组件中的可复用功能。

本质其实就是一个js对象,它可以包含我们组件中任意功能选项,如datacomponentsmethodscreatedcomputed等等。

我们只要将共用的功能以对象的方式传入 mixins选项中,当组件使用 mixins对象时所有mixins对象的选项都将被混入该组件本身的选项中来。

Vue中我们可以局部混入全局混入

局部混入

定义一个mixin对象,有组件optionsdatamethods属性

var myMixin = {created: function () {this.hello()},methods: {hello: function () {console.log('hello from mixin!')}}
}

组件通过mixins属性调用mixin对象

Vue.component('componentA',{mixins: [myMixin]
})

该组件在使用的时候,混合了mixin里面的方法,在自动执行create生命钩子,执行hello方法

全局混入

通过 Vue.mixin() 进行全局的混入

Vue.mixin({created: function () {console.log("全局混入")}
})

使用全局混入需要特别注意,因为它会影响到每一个组件实例(包括第三方组件)

全局混入常用于插件的编写

注意事项:

  • 当组件存在与mixin对象相同的选项的时候,进行递归合并的时候组件的选项会覆盖mixin的选项

  • 但是如果相同选项为生命周期钩子的时候,会合并成一个数组,先执行mixin的钩子,再执行组件的钩子

二、使用场景

在日常的开发中,我们经常会遇到在不同的组件中经常会需要用到一些相同或者相似的代码,这些代码的功能相对独立

这时,可以通过Vue的mixin功能将相同或者相似的代码提出来

举例:定义一个modal弹窗组件,内部通过isShowing来控制显示

const Modal = {template: '#modal',data() {return {isShowing: false}},methods: {toggleShow() {this.isShowing = !this.isShowing;}}
}

定义一个tooltip提示框,内部通过isShowing来控制显示

const Tooltip = {template: '#tooltip',data() {return {isShowing: false}},methods: {toggleShow() {this.isShowing = !this.isShowing;}}
}

通过观察上面两个组件,发现两者的逻辑是相同,代码控制显示也是相同的,这时候mixin就派上用场了

首先抽出共同代码,编写一个mixin

const toggle = {data() {return {isShowing: false}},methods: {toggleShow() {this.isShowing = !this.isShowing;}}
}

两个组件在使用上,只需要引入mixin

const Modal = {template: '#modal',mixins: [toggle]
};const Tooltip = {template: '#tooltip',mixins: [toggle]
}

通过上面例子,让我们知道mixin对于封装一些可复用的功能如此有趣、方便、实用。

三、源码分析

首先从Vue.mixin入手

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

主要是调用merOptions方法

export function mergeOptions (parent: Object,child: Object,vm?: Component
): Object {if (child.mixins) { // 判断有没有mixin 也就是mixin里面挂mixin的情况 有的话递归进行合并for (let i = 0, l = child.mixins.length; i < l; i++) {parent = mergeOptions(parent, child.mixins[i], vm)}
}const options = {} let keyfor (key in parent) {mergeField(key) // 先遍历parent的key 调对应的strats[XXX]方法进行合并}for (key in child) {if (!hasOwn(parent, key)) { // 如果parent已经处理过某个key 就不处理了mergeField(key) // 处理child中的key 也就parent中没有处理过的key}}function mergeField (key) {const strat = strats[key] || defaultStratoptions[key] = strat(parent[key], child[key], vm, key) // 根据不同类型的options调用strats中不同的方法进行合并}return options
}

从上面的源码,我们得到以下几点:

  • 优先递归处理 mixins
  • 先遍历合并parent 中的key,调用mergeField方法进行合并,然后保存在变量options
  • 再遍历 child,合并补上 parent 中没有的key,调用mergeField方法进行合并,保存在变量options
  • 通过 mergeField 函数进行了合并

下面是关于Vue的几种类型的合并策略

  • 替换型
  • 合并型
  • 队列型
  • 叠加型

替换型

替换型合并有propsmethodsinjectcomputed

strats.props =
strats.methods =
strats.inject =
strats.computed = function (parentVal: ?Object,childVal: ?Object,vm?: Component,key: string
): ?Object {if (!parentVal) return childVal // 如果parentVal没有值,直接返回childValconst ret = Object.create(null) // 创建一个第三方对象 retextend(ret, parentVal) // extend方法实际是把parentVal的属性复制到ret中if (childVal) extend(ret, childVal) // 把childVal的属性复制到ret中return ret
}
strats.provide = mergeDataOrFn

同名的propsmethodsinjectcomputed会被后来者代替

合并型

和并型合并有:data

strats.data = function(parentVal, childVal, vm) {    return mergeDataOrFn(parentVal, childVal, vm)
};function mergeDataOrFn(parentVal, childVal, vm) {    return function mergedInstanceDataFn() {        var childData = childVal.call(vm, vm) // 执行data挂的函数得到对象var parentData = parentVal.call(vm, vm)        if (childData) {            return mergeData(childData, parentData) // 将2个对象进行合并                                 } else {            return parentData // 如果没有childData 直接返回parentData}}
}function mergeData(to, from) {    if (!from) return to    var key, toVal, fromVal;    var keys = Object.keys(from);   for (var i = 0; i < keys.length; i++) {key = keys[i];toVal = to[key];fromVal = from[key];    // 如果不存在这个属性,就重新设置if (!to.hasOwnProperty(key)) {set(to, key, fromVal);}      // 存在相同属性,合并对象else if (typeof toVal =="object" && typeof fromVal =="object") {mergeData(toVal, fromVal);}}    return to
}

mergeData函数遍历了要合并的 data 的所有属性,然后根据不同情况进行合并:

  • 当目标 data 对象不包含当前属性时,调用 set 方法进行合并(set方法其实就是一些合并重新赋值的方法)
  • 当目标 data 对象包含当前属性并且当前值为纯对象时,递归合并当前对象值,这样做是为了防止对象存在新增属性

队列性

队列性合并有:全部生命周期watch

function mergeHook (parentVal: ?Array<Function>,childVal: ?Function | ?Array<Function>
): ?Array<Function> {return childVal? parentVal? parentVal.concat(childVal): Array.isArray(childVal)? childVal: [childVal]: parentVal
}LIFECYCLE_HOOKS.forEach(hook => {strats[hook] = mergeHook
})// watch
strats.watch = function (parentVal,childVal,vm,key
) {// work around Firefox's Object.prototype.watch...if (parentVal === nativeWatch) { parentVal = undefined; }if (childVal === nativeWatch) { childVal = undefined; }/* istanbul ignore if */if (!childVal) { return Object.create(parentVal || null) }{assertObjectType(key, childVal, vm);}if (!parentVal) { return childVal }var ret = {};extend(ret, parentVal);for (var key$1 in childVal) {var parent = ret[key$1];var child = childVal[key$1];if (parent && !Array.isArray(parent)) {parent = [parent];}ret[key$1] = parent? parent.concat(child): Array.isArray(child) ? child : [child];}return ret
};

生命周期钩子和watch被合并为一个数组,然后正序遍历一次执行

叠加型

叠加型合并有:componentdirectivesfilters

strats.components=
strats.directives=strats.filters = function mergeAssets(parentVal, childVal, vm, key
) {    var res = Object.create(parentVal || null);    if (childVal) { for (var key in childVal) {res[key] = childVal[key];}   } return res
}

叠加型主要是通过原型链进行层层的叠加

通过上述总结出:

  1. 替换型策略有propsmethodsinjectcomputed,就是将新的同名参数替代旧的参数
  2. 合并型策略是data, 通过set方法进行合并和重新赋值
  3. 队列型策略有生命周期函数watch,原理是将函数存入一个数组,然后正序遍历依次执行
  4. 叠加型有componentdirectivesfilters,通过原型链进行层层的叠加

四、Mixin 在 UE 设计中具有以下优点和缺点

优点:

  1. 代码复用:Mixin 可以将可复用的功能单元定义为独立模块,通过注入到不同的对象或组件中进行复用,避免了重复编写相同的代码,提高了代码的可维护性和重用性。

  2. 功能扩展:通过注入额外的功能,Mixin 可以扩展对象或组件的能力,使其拥有更多的行为和特性,从而增强了用户体验。

  3. 灵活组合:Mixin 允许多个功能组合成一个整体,可以根据需要将不同的 Mixin 组合起来,创建具有多种功能的对象或组件,提供更丰富的用户体验。

  4. 解耦和灵活性:Mixin 的使用可以降低代码间的耦合度,功能与对象解耦,使得代码更加灵活、可测试,便于进行模块化和重构。

缺点(需注意点):

  • 命名冲突:使用多个 Mixin 时,如果命名冲突可能会导致代码冲突或覆盖,需要谨慎管理命名,避免命名冲突产生意外结果。

  • 复杂性增加:当使用多个 Mixin 时,可能会增加代码的复杂性,特别是在处理多个 Mixin 之间的依赖关系和执行顺序时,需要仔细管理。

  • 隐式依赖:Mixin 的使用可能导致代码间的隐式依赖关系,使得代码更加难以理解和维护,特别是在大型项目中。

  • 增加理解成本:对于不熟悉 Mixin 的开发人员,理解和使用 Mixin 可能需要额外的学习成本,特别是在处理复杂的 Mixin 组合和冲突解决时。

综上所述,Mixin 在 UE 设计中具有代码复用、功能扩展和灵活组合等优点,但也存在命名冲突、复杂性增加、隐式依赖和理解成本增加等缺点。因此,在使用 Mixin 时需要权衡利弊,并根据具体情况做出合理的选择和管理。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/198960.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Comprehension from Chaos: Towards Informed Consent for Private Computation

目录 笔记后续的研究方向摘要引言 Comprehension from Chaos: Towards Informed Consent for Private Computation CCS 2023 笔记 本文探讨了用户对私有计算的理解和期望&#xff0c;其中包括多方计算和私有查询执行等技术。该研究进行了 22 次半结构化访谈&#xff0c;以调查…

C++异常的使用

1.传统错误 在C语言中&#xff0c;传统的错误处理方式有&#xff1a; assert()&#xff0c;缺陷就是太过于武断&#xff0c;会直接终止程序&#xff0c;并且只能在debug模式下才可以起作用返回错误码&#xff0c;在Linux编程中就十分常见&#xff0c;但是对于很深层的系统调用…

14、SQL注入——HTTP文件头注入

文章目录 一、HTTP Header概述1.1 HTTP工作原理1.2 HTTP报文类型1.3 较重要的HTTP Header内容 二、HTTP Header注入2.1 HTTP Header注入的前提条件2.2 常见的HTTP Header注入类型 一、HTTP Header概述 1.1 HTTP工作原理 1.2 HTTP报文类型 &#xff08;1&#xff09;请求报文 …

国产光耦ORPC-817替代HCPL-817-36BE,在找国产的朋友联系沟通

国产光耦ORPC-817替代HCPL-817-36BE&#xff0c;在找国产的朋友联系沟通 北京冠宇铭通 肖小姐 1. 特性 (1)电流传递比(中频 5mA, VCE 5V时&#xff0c;CTR:最小50%) (2)输入输出隔离电压高(Viso 5000 vrms) (3)响应时间(tr: TYP。4s (VCE 2V, IC 2mA, RL 100Ω) (4) ESD…

软件设计模式原则(五)接口隔离原则

顾名思义&#xff0c;该原则说的是&#xff1a;客户端不应该依赖它不需要的接口。一个类对另一个类的依赖应该建立在最小的接口上。 一.定义 核心思想&#xff1a; 使用多个专门的接口比使用单一的总接口要好。一个类对另外一个类的依赖性应当是建立在最小的接口上的。一个接口…

博客文章SEO:提升博客排名和吸引更多读者的方法来啦!

互联网发展到现在&#xff0c;搜索引擎优化&#xff08;SEO&#xff09;一直发挥着不可替代的作用。搜索引擎的流量往往更加定向&#xff0c;来自搜索引擎的流量转化率更高&#xff0c;可以帮助企业更好地实现销售和推广目标。因此&#xff0c;通过合理的SEO策略&#xff0c;你…

Arduino驱动STS35数字温度传感器(温湿度传感器)

目录 1、传感器特性 2、硬件原理图 3、控制器和传感器连线图 4、驱动程序 STS35瑞士Sensirion公司新推出的温度传感器,STS35提供了一个完全校准、线性和供电电压补偿的数字输出&

服务器是否稳定怎么看

服务器是否稳定怎么看 在对服务器进行测试时&#xff0c;难免会遇到一些出错的现象&#xff0c;而这些现象都可以被很快的解决。那么服务器状态出错情况有哪些&#xff1f;怎么看服务器是否稳定&#xff1f;壹基比小鑫给大家说说这些出错状态的意思&#xff01; 一、怎么看服…

市场调研:中国南美白对虾养殖面积达到17.75万公顷

南美白对虾(学名:Litopenaeus Vannamei )是对虾科、滨对虾属动物。成体最长达23厘米&#xff0c;甲壳较薄&#xff0c;正常体色为青蓝色或浅青灰色&#xff0c;全身不具斑纹。步足常呈白垩状&#xff0c;故有白肢虾之称。南美白对虾额角尖端的长度不超出第1触角柄的2节&#xf…

从浅入深掌握进阶结构体(C语言)

前言 这一期我们将继续讲解结构体的知识&#xff0c;还没有看过上一期的小伙伴一定要赶紧去学习哦。 上一期&#xff0c;冲鸭&#xff01; 那么话不多说我们开始今天的学习吧&#xff01; 文章目录 1,结构体的自引用2,匿名结构体3,位段4,结构体的传参5,尾声 1,结构体的自引用 …

基因组注释流程

一边学习&#xff0c;一边总结&#xff0c;一边分享&#xff01; 详细教程请访问&#xff1a; 组学分析流程 本期分析流程 Hisat2-SamtoolsTrinity_GG_denovoPASA … 本期教程文章 题目&#xff1a;Genomic insights into local adaptation and future climate-induced vu…

【开源视频联动物联网平台】libmodbus 写一个Modbus TCP 客户端

libmodbus 是一个用于 Modbus 通信协议的 C 语言库&#xff0c;可以用来创建 Modbus TCP 客户端。以下是一个简单的示例代码&#xff0c;演示如何使用 libmodbus 创建一个 Modbus TCP 客户端。 首先&#xff0c;确保你已经安装了 libmodbus 库。你可以从 libmodbus 的官方网站…

FastAPI与BaseModel

from typing import Optionalfrom fastapi import FastAPI from pydantic import BaseModel #当一个模型属性具有默认值时&#xff0c;它不是必需的。否则它是一个必需属性。将默认值设为 None 可使其成为可选属性 app FastAPI() class Item(BaseModel):name:str #没有初始值都…

linux 安装 Apache 服务 并部署网站

作者简介&#xff1a;一名云计算网络运维人员、每天分享网络与运维的技术与干货。 公众号&#xff1a;网络豆云计算学堂 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a; 网络豆的主页​​​​​ 写在前面 哈喽大家我是网络豆&#xff0c;本章将会…

数据结构—二叉树

文章目录 10.二叉树(1).二叉树的基本概念(2).遍历#1.前序遍历#2.中序遍历#3.后序遍历#4.非递归中序遍历 (3).中序前/后序建树#1.中序前序遍历建树#2.中序后序遍历建树 (4).递归和二叉树基本操作#1.求树高#2.求结点数#3.求叶子结点数#4.复制树#5.判断两棵树是否相等 (5).特殊二叉…

零信任组件和实施

零信任是一种安全标准&#xff0c;其功能遵循“从不信任&#xff0c;始终验证”的原则&#xff0c;并确保没有用户或设备受信任&#xff0c;无论他们是在组织网络内部还是外部。简而言之&#xff0c;零信任模型消除了信任组织安全边界内任何内容的概念&#xff0c;而是倡导严格…

操作系统复习总结——文件管理

&#x1f525;博客主页&#xff1a;真的睡不醒 &#x1f680;系列专栏&#xff1a;深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 &#x1f498;每日语录&#xff1a;但愿每次回忆&#xff0c;对生活都不感到负疚。 &#x1f389;感谢大家点赞…

搜维尔科技:AI时代,迈向2030元宇宙数字人戏曲教育数字化思维、战略与未来!

一场关于中国传统戏曲与数字媒体交汇的探讨之旅将于今日在清华大学开讲&#xff0c;本次活动旨在推动AI时代大背景下&#xff0c;利用元宇宙、数字人等创新技术焕发中国传统戏曲全新活力。 讲座以“AI时代&#xff0c;迈向2030元宇宙数字人戏曲教育数字化思维、战略与未来”为主…

【Linux系统编程】开发工具yum和vim

目录 一&#xff0c;yum工具的使用 1&#xff0c;yum的介绍 2&#xff0c;yum的使用 二&#xff0c;vim工具的开发 1&#xff0c;vim的介绍 2&#xff0c;模式的使用 3&#xff0c;vim配置文件 4&#xff0c;sudo配置文件 一&#xff0c;yum工具的使用 1&#xff0c;y…

弱口令防护和网站防盗链有什么用

弱口令防护主要针对用户账户的安全。弱口令是指容易被猜测或破解的密码&#xff0c;如常见的密码、简单的数字序列或字典中的单词等。弱口令防护的目的是防止恶意用户或攻击者通过猜测或暴力破解密码的方式获取合法用户的账户权限。通过实施强密码策略、密码复杂度要求和账户锁…