聊聊Vue中$set是如何实现的?
在日常开发中,
$set
的也是一个非常实用的API,因为Vue2实现响应式的核心是利用了ES5的Object.defineProperty
,当我们通过直接修改数组下标更改数组或者给对象添加新的属性,这个时候Object.defineproperty是监听不到数据的变化的,这时候大家就会用上$set
,让修改的操作也实现响应,我们知其然更要知其所以然,接下来看一下Vue中的$set是如何实现的。【相关推荐:vuejs视频教程、web前端开发】
应用场景
let dataArr = ["item1"]; let dataObject = { name: "ccs" }; dataArr[2] = "item2"; dataObject.age = 22; 响应失败,页面没有显示更新新增的数据 this.$set(this.dataArr,2,'item2') this.$set(this.dataObject,'age',22) 响应成功,页面显示更新新增的数据
set实现
接下来我们看一下$set在Vue中的定义
function set(target: Array<any> | Object, key: any, val: any): any { if ( process.env.NODE_ENV !== "production" && (isUndef(target) || isPrimitive(target)) ) { warn( `Cannot set reactive property on undefined, null, or primitive value: ${(target: any)}` ); } if (Array.isArray(target) && isValidArrayIndex(key)) { target.length = Math.max(target.length, key); target.splice(key, 1, val); return val; } if (key in target && !(key in Object.prototype)) { target[key] = val; return val; } const ob = (target: any).__ob__; if (target._isVue || (ob && ob.vmCount)) { process.env.NODE_ENV !== "production" && warn( "Avoid adding reactive properties to a Vue instance or its root $data " + "at runtime - declare it upfront in the data option." ); return val; } if (!ob) { target[key] = val; return val; } defineReactive(ob.value, key, val); ob.dep.notify(); return val; }
在源码中首先判断set的目标是否是undefined
和基本类型
如果是undefined
或基本类型
就报错,
因为用户不应该往undefined和基本类型中set东西,
然后又判断了目标是否是数组与key是不是合法的index,合法的index是指值为大于等于0的整数,
如果两个条件都成立就对目标数组调用splice方法插入或者修改数组
,
这里的splice
不是普通的splice
,是王维诗里的splice,是被vue代理重写过的splice
数组实现响应
$set实现数组修改响应的方式是代理重写的数组的一部分方法,接下来我们看一下具体实现
const arrayProto = Array.prototype export const arrayMethods = Object.create(arrayProto) const methodsToPatch = [ 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse' ] function def(obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: !!enumerable, writable: true, configurable: true }); } methodsToPatch.forEach(function (method) { const original = arrayProto[method] def(arrayMethods, method, function mutator (...args) { const result = original.apply(this, args) const ob = this.__ob__ let inserted switch (method) { case 'push': case 'unshift': inserted = args break case 'splice': inserted = args.slice(2) break } if (inserted) ob.observeArray(inserted) ob.dep.notify() return result }) })
vue中代理重写的不只是splice
,有push、pop、shift、unshift、splice、sort、reverse
这七个方法,
首先执行了const result = original.apply(this, args)
执行原本数组的方法并获取它的值,接下来判断如果是往数组中添加值就将新添加的值也实现响应式
,
最后一步拿到这个数组的_ob_对象
对_ob_
里的dep进行派发更新。
想深入了解vue的响应式可以查阅往期文章
面试官问你Vue2的响应式原理,你怎么答? - 掘金 (juejin.cn)
对象实现响应
$set
中下半部分的逻辑就是用来处理对象响应的,我们接着往下看
if (key in target && !(key in Object.prototype)) { target[key] = val; return val; } const ob = (target: any).__ob__; if (!ob) { target[key] = val; return val; } defineReactive(ob.value, key, val); ob.dep.notify(); return val;
首先判断了属性如果在目标对象中直接return结束逻辑,
因为vue只有添加目标对象中原本没有的属性时才会失去响应,例如 let obj={} obj.name='ccs'
,
vue在初始化的时候会将data里的所有属性都变成响应式,如果的值是对象或者数组则会new一个Observer
实例储存在__ob__,想深入了解vue的响应式可以查阅往期文章
面试官问你Vue2的响应式原理,你怎么答? - 掘金 (juejin.cn)
拿到这个对象的_ob_进行判断,如果不存在就说明是未经过vue初始化的普通对象而不是响应式对象否则就手动通过defineReactive
为属性添加get方法与set方法实现响应,
然后手动调用dep
里的notify()
发布更新。
总结
vue中$set方法对数组和对象的处理本质上的一样的,对新增的值添加响应然后手动触发派发更新。
以上是聊聊Vue中$set是如何实现的?的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

使用vue框架开发前端项目时,我们部署的时候都会部署多套环境,往往开发、测试以及线上环境调用的接口域名都是不一样的。如何能做到区分呢?那就是使用环境变量和模式。

Ace 是一个用 JavaScript 编写的可嵌入代码编辑器。它与 Sublime、Vim 和 TextMate 等原生编辑器的功能和性能相匹配。它可以很容易地嵌入到任何网页和 JavaScript 应用程序中。Ace 被维护为Cloud9 IDE的主要编辑器 ,并且是 Mozilla Skywriter (Bespin) 项目的继承者。

组件化和模块化的区别:模块化是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个每个功能模块的职能一致。组件化是从UI界面的角度进行规划;前端的组件化,方便UI组件的重用。

当今前端开发中,Vue.js 已经成为了一个非常流行的框架。随着 Vue.js 的不断发展,单元测试变得越来越重要。今天,我们将探讨如何在 Vue.js 3 中编写单元测试,并提供一些最佳实践和常见的问题及解决方案。

前言:在vue3的开发中,reactive是提供实现响应式数据的方法。日常开发这个是使用频率很高的api。这篇文章笔者就来探索其内部运行机制。

在Vue.js中,开发人员可以使用两种不同的语法来创建用户界面:JSX语法和模板语法。这两种语法各有优劣,下面就来探讨一下它们的区别和优劣势。

查询当前vue版本的两种方法:1、在cmd控制台内,执行“npm list vue”命令查询版本,输出结果就是vue的版本号信息;2、在项目中找到并打开package.json文件,查找“dependencies”项即可看到vue的版本信息。
