面试官:说说你对vue的mixin的理解,有什么应用场景?

一、mixin是什么

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

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

Vue中的mixin

先来看一下官方定义

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

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

我们只要将共用的功能以对象的方式传入 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里面的方法,在自动执行created生命钩子,执行hello方法

全局混入

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

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

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

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

注意事项:

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

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

二、使用场景

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

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

举个例子

定义一个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入手

源码位置:/src/core/global-api/mixin.js

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

主要是调用merOptions方法

源码位置:/src/core/util/options.js

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
}

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

小结:

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

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Vue 中常用的基础指令

一. 什么是 Vue 指令 指令的定义和作用 指令是通过 Vue 实例的directives选项进行定义的。在指令的定义中&#xff0c;需要提供一个bind函数&#xff0c;它在指令第一次绑定到元素时被调用&#xff0c;可以执行一些初始化的操作。还可以提供update函数&#xff0c;它在指令所…

CCF201909_1

题解&#xff1a; #include<bits/stdc.h> using namespace std;struct tree {int id;int apple;int cut 0; };bool cmp(tree a, tree b) {if (a.cut b.cut){return a.id < b.id;}return a.cut > b.cut; }int main() {int n, m;cin >> n >> m;tree t…

成本估算模型

答案&#xff1a;B 知识点&#xff1a; COCOMO II模型 应用组装模型 对象点 早期设计阶段模型 功能点&#xff0c;代码行 体系结构阶段模型 代码行 解析&#xff1a; 基本COCOMO计算成本看代码量 中级COCOMO看代码量&#xff0c;硬件&#xff0c;人员等因素 详细CO…

2024逼自己做AI副业!月入2w+!

最近&#xff0c;身边朋友都在为赚钱发愁&#xff0c;加上大环境不行&#xff0c;心里更慌了。 对大部分人来说&#xff0c;工资只能缓解**“没钱”的****恐惧**&#xff0c;却不能改变“没钱”的事实。 但是&#xff0c;有这么一群人&#xff0c;踩中了**“AI”风口&#xf…

Maven从入门到精通(二)

一、什么是pom.xml pom.xml是Maven项目的核心配置文件&#xff0c;它是 项目对象模型 - Project Object Model&#xff08;POM&#xff09;的缩写。POM定义了项目的所有属性&#xff0c;包括项目的名称、版本、依赖关系、构建配置等。使用pom.xml&#xff0c;我们可以轻松地管…

安全装备检测系统源码分享

安全装备检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vis…

c#如何读取Modbus中Slave和Poll的值

虚拟串口 Modbus Slave 右击设置slave定义 设置好地址后&#xff0c;设置连接。点击Connection–选择Connect Modbus Poll 右击选择设置定义 设置的内容要和slave一致 设置连接&#xff0c;点击Connection—选择Connect Poll和Slave连接之后&#xff0c;可以获取slave的值。我…

荣誉上榜!亲笔签入选2024年度重庆市网络安全优秀产品和技术名单

近日&#xff0c;在由重庆市委网信办与市经济信息委联合发起的网络安全优秀产品及技术评选活动中&#xff0c;亲笔签数字科技“数字笔迹可信身份认证系统”凭借其领先的安全隐私保护能力&#xff0c;以及在数字经济交易场景中广泛的应用潜力&#xff0c;成功入选《2024年重庆市…

探索代码的守护者:Pyflakes,Python代码的隐形盾牌

文章目录 探索代码的守护者&#xff1a;Pyflakes&#xff0c;Python代码的隐形盾牌第一部分&#xff1a;背景介绍第二部分&#xff1a;Pyflakes是什么&#xff1f;第三部分&#xff1a;如何安装Pyflakes&#xff1f;第四部分&#xff1a;Pyflakes的简单使用方法第五部分&#x…

一步步教你利用大模型开发个性化AI应用,告别‘人工智障’!

为了回答这个问题&#xff0c;我用说人话的方式拿gpts创建了一个“我”&#xff0c;然后让她来回答这个问题。&#xff08;确认过眼神&#xff0c;我是懂套娃的&#xff09; 接下来我会先展示下整个定制过程&#xff1b;然后我们一起看一下她能把题答到什么程度&#xff1b;最后…

AI生成头像表情包,一次十分钟,就能实现月入过万的玩法,无脑操作

今天给大家带来的项目是AI生成表情包和头像&#xff0c;这个项目对于我们做ip来说是真心不错&#xff0c;就比如我这个头像。 为什么说每天只需要10分钟呢&#xff0c;那么我们继续往下看。 "项目介绍 这个项目的核心其实就是使用AI生成表情包或者说生成头像&#xff0c…

828华为云征文|华为云 Flexus云服务器X实例-选购到创建宝塔

文章目录 1.华为云 Flexus云服务器X实例介绍1.1 产品优势1.2应用场景概览 2.选择配置与购买2.1 计费模式与区域选择2.2 实例规格2.3 镜像2.4 存储与网络2.5 弹性公网IP2.6 云服务器名称与登录凭证2.7 云备份 3.使用CloudShell 登录Flexus云服务器X实例3.1 CloudShell 4.创建宝塔…

【SSRF漏洞】——http协议常见绕过

改变的确很难&#xff0c;但结果值得冒险 本文如有错误之处&#xff0c;还请各位师傅指正 一.ssrf概述 SSRF全称为Server-side Request Fogery,中文含义服务器端请求伪造 SSRF是一种由攻击者构造形成由目标服务端发起请求的一个安全漏洞。一般情况下&#xff0c;SSRF攻击的目标…

AI+教育|拥抱AI智能科技,让课堂更生动高效

AI在教育领域的应用正逐渐成为现实&#xff0c;提供互动性强的学习体验&#xff0c;正在改变传统教育模式。AI不仅改变了传统的教学模式&#xff0c;还为教育提供了更多的可能性和解决方案。从个性化学习体验到自动化管理任务&#xff0c;AI正在全方位提升教育质量和效率。随着…

运行PaddleOCR报错:requests.exceptions.SSLError: HTTPSconnectionPool……

文章目录 问题描述解决方法 问题描述 在运行以下代码时报错&#xff1a; ocr PaddleOCR(lang"en")解决方法 打开cmd&#xff0c;输入以下命令&#xff0c;查找Python解释器所在路径。 找到 Lib\site-packages\paddleocr\ppocr\utils\network.py&#xff0c;将代码…

docker-compose elasticsearch 集群搭建(用户登录+https访问)

文章目录 前言docker-compose elasticsearch 集群搭建(用户登录https访问)1. 效果2. 制作elasticsearch 分词器镜像2.1. 拉取elasticsearch:7.11.12.2. 制作特定版本镜像 3. docker-compose elasticsearch 集群制作4. es账户密码初始化 前言 如果您觉得有用的话&#xff0c;记…

小红书治愈插画副业,猛猛涨粉上万+,每天只用5分钟

在这个数字化时代&#xff0c;AI技术正以前所未有的速度改变着我们的生活和工作。特别是在内容创作领域&#xff0c;AI的运用已经催生了一种全新的创作模式。一幅幅温馨可爱的治愈插画如同清流&#xff0c;不仅契合当下年轻人生活的状态&#xff0c;更成为许多人表达生活态度、…

【鸿蒙】HarmonyOS NEXT星河入门到实战8-自定义组件-组件通信

目录 1、模块化语法 1.1 模块化基本认知 1.2 默认导出和导入 1.2.1 在ets下新建tools目录 1.2.2 在tools下新建moduls.ets文件 1.2.3 index.ets 1.3 按需导出和导入 1.4 全部导入 2、自定义组件 -基础 2.1 自定义组件 - 基本使用 2.2 自定义组件 -通用样式 2.2.1 et…

ceph简介

ceph存储简要概述&#xff1a; 通过将文件分解成固定大小对象&#xff0c;然后存放于pool中&#xff0c;每个pool中 可包含多个pg&#xff0c;每个pg中又可包含多个osd 通过crush算法 最终数据落盘到osd中去。 一、ceph 删除osd 步骤1 修改osd数据操作权重值 ceph osd crush r…

雷达液位计助力造纸行业精准测量

雷达液位计助力造纸行业精准测量 造纸工业是国民经济的基础原材料工业&#xff0c;是与社会文明和经济发展息息相关的重要产业。造纸是一个复杂的传质传热的工业过程&#xff0c;主要分为制浆和造纸两部分。为了保障造纸厂的连续运行&#xff0c;必须储备大量制备好的纸浆&…