首页IT科技object数组怎么转成int数组(Object.assign触发watch原理示例解析)

object数组怎么转成int数组(Object.assign触发watch原理示例解析)

时间2025-06-20 04:42:38分类IT科技浏览4275
导读:为什么可以用Object.assign触发$watch Object.assign,这个api在简单拷贝可枚举对象的属性值时经常用到。这里介绍一个在vue2中Object.assign的用法,这个用法在官网文档 有详细介绍:...

为什么可以用Object.assign触发$watch

Object.assign            ,这个api在简单拷贝可枚举对象的属性值时经常用到            。这里介绍一个在vue2中Object.assign的用法                  ,这个用法在官网文档 有详细介绍:

watch: { someObject(nvalue, ovalue) { ... } } // 为对象添加新属性 this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 })

而且要注意的是如果像下面这样添加上去的新属性无法触发更新:

this.someObject = Object.assign(this.someObject, { a: 1, b: 2 })

问题是为什么前面那种写法会有效?

先看vue2文档

在vue2的文档中有详细说明     ,在组件的依赖收集过程中      ,所有property 在被访问和修改时会通知变更                  ,对于对象来说           ,Vue 无法检测 property 的添加或移除                 。

一般情况下      ,在vue中                  ,如果要对data对象中实例添加根级别property           ,我们可以这样操作:

Vue.set(someObject, name, value)

或者这样操作

this.$set(this.someObject,name,2)

但是如果我们要对一个对象添加多个属性,同时还要保持对象的响应性                  ,这种情况下就要用到开篇提到的方法      。

在mdn 上                 ,对 Object.assign 有这一句解释:该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter            。对这句            ,我们用下面的例子a来理解                 。

var obj = {}; var c = null Object.defineProperty(obj, c, {   set:function(x){     console.log(c被赋值:,x);     c=x   },   get:function(){     console.log(c被取出:,c)     return c   } }) obj.c=3 //c被赋值: 3 obj.c //c被取出: 3 obj = Object.assign(obj, {c: wer23e}) // 触发了set! obj = Object.assign(obj, {a: wer23e}) // 由于事先未用defineProperty定义a                 ,所以无法监听 // 由于目标对象未定义属性     ,无法监听 obj = Object.assign({},obj, {a: wer23e,c: dfrr23e})

通过这段代码可以理解上面说的“Object.assign会使用目标对象的[[Set]]            ”            ,同时                  ,这段代码也演示了vue2中响应原理     ,因为vue2中所有需要响应的属性都是用 Object.defineProperty 进行响应绑定      ,这样所有的访问和修改动作都会被追踪到      。

但是对于没有事先被 Object.defineProperty定义的属性                  ,比如添加一个属性就无法监听到了      。在上面的示例中           ,即使我用文档提到的用法 obj = Object.assign({},obj, {a: wer23e,c: dfrr23e}) 仍然无法触发c属性的 set                 。走到这一步      ,是不是得看watch源码了?其实不必!

用Object.assign触发watch原理

针对这个问题                  ,watch的源码不必看           ,但是 Object.assign 的源码必须要看,

if (typeof Object.assign !== function) { // Must be writable: true, enumerable: false, configurable: true Object.defineProperty(Object, "assign", { value: function assign(target, varArgs) { // .length of function is 2 use strict; if (target === null || target === undefined) { throw new TypeError(Cannot convert undefined or null to object); } var to = Object(target); for (var index = 1; index < arguments.length; index++) { var nextSource = arguments[index]; if (nextSource !== null && nextSource !== undefined) { for (var nextKey in nextSource) { // Avoid bugs when hasOwnProperty is shadowed if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { to[nextKey] = nextSource[nextKey]; } } } } return to; }, writable: true, configurable: true }); }

其实就是把 assign 方法中的参数的可枚举属性全部复制到此方法的第一参数上去            。回头再去理解下例子a                  , obj = Object.assign({},obj, {a: wer23e,c: dfrr23e}) 无法触发c属性的 set 函数是因为                 ,obj引用关系已经被改变了,不再是原来那个对象            ,也就没有了对应的属性监控                 ,但是为什么官方文档会建议这么用呢?

接下来     ,我写了个小demo            ,来帮你理解                  ,你可以试下效果

<template> <div @click="clickme()"> 点我啊 {{ test.a }}</div> </template> <script> export default { data() { test: { a: 3 }, }, watch: { test(n, o) { debugger console.log(n) } }, methods: { clickme() { debugger this.test = Object.assign(this.test, { a: 1 }) debugger this.test = Object.assign(this.test, { a: 1, b: 2 }) debugger this.test = Object.assign({}, this.test, { a: 1, b: 2 }) }, } } </script>

可以看到     ,确实      ,最后一种Object.assign方法会触发test对象监听      。前面两种写法                  ,只能触发对象的属性更新响应           ,如果给obj对象添加属性      ,就无法监测到obj的变化                 。到这一步                  ,其实如果要彻底弄清楚           ,最好还是看下 watch 源码            。我在仔细分析了后,才发现其实跟watch源码没有什么关系                  ,所以本文就不展开分析了                 ,这是另一篇文章的事了。

如果看不明白 watch 源码也没关系,其实简单解释就是            ,用obj = Object.assign({},obj, {a: wer23e,c: dfrr23e}) 这种方式                 ,改变了obj的引用关系     ,也就是obj的值变了            ,所以如果你在watch函数中监听了obj                  ,obj是变化了的     ,只不过obj的值是一个 Object 对象而已      ,所以会触发obj对象的响应                 。

参考资料:

cn.vuejs.org/v2/guide/re…

developer.mozilla.org/zh-CN/docs/…

https://www.jb51.net/article/265630.htm

https://www.jb51.net/article/266683.htm

以上就是Object.assign触发watch原理示例解析的详细内容                  ,更多关于Object.assign触发watch的资料请关注本站其它相关文章!

声明:本站所有文章           ,如无特殊说明或标注      ,均为本站原创发布                 。任何个人或组织                  ,在未征得本站同意时           ,禁止复制            、盗用                 、采集      、发布本站内容到任何网站            、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理            。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
网站对网速有影响吗知乎(网站对网速有影响吗安全吗)