返回顶部
首页 > 资讯 > 前端开发 > JavaScript >Object.assign触发watch原理示例解析
  • 460
分享到

Object.assign触发watch原理示例解析

Object.assign触发watchObject assign watch 2022-11-13 19:11:04 460人浏览 独家记忆
摘要

目录为什么可以用Object.assign触发$watch先看Vue2文档用Object.assign触发watch原理为什么可以用Object.assign触发$watch Obj

为什么可以用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 style="width: 100px; height: 50px; position: absolute; top: 100px" @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的资料请关注编程网其它相关文章!

--结束END--

本文标题: Object.assign触发watch原理示例解析

本文链接: https://lsjlt.com/news/170735.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Object.assign触发watch原理示例解析
    目录为什么可以用Object.assign触发$watch先看vue2文档用Object.assign触发watch原理为什么可以用Object.assign触发$watch Obj...
    99+
    2022-11-13
    Object.assign触发watch Object assign watch
  • mysql触发器原理与用法实例分析
    本文实例讲述了mysql触发器原理与用法。分享给大家供大家参考,具体如下: 本文内容: 什么是触发器 创建触发器 单条触发器语句 多条触发器语句 查看触发器 删除触...
    99+
    2022-05-22
    mysql 触发器
  • zookeeper的watch机制原理解析
    目录一、Watch机制介绍二、zkCli客户端使⽤watch2.1、get -w命令详解2.2、ls -w命令详解2.3、ls -R -w命令详解三、curator客户端使⽤watc...
    99+
    2024-04-02
  • CLR触发器的示例分析
    这篇文章主要介绍了CLR触发器的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。CLR触发器实现代码:[Microsoft.SqlServer.Server.SqlTr...
    99+
    2023-06-17
  • RxJava 触发流基本原理源码解析
    目录正文触发流小结总结正文 本节,我们从Rxjava使用代码入手,去结合自己已有的知识体系,加查阅部分源码验证的方式,来一起探索一下Rxjava实现的基本原理。 为了本文原理分析环...
    99+
    2022-12-30
    RxJava 触发流原理 RxJava 触发流
  • Kotlin协程之Flow触发与消费示例解析
    目录示例一.Flow的触发与消费1.onEach方法2.transform方法3.collect方法二.多消费过程的执行三.总结示例 代码如下: launch(Dispatchers...
    99+
    2024-04-02
  • jsjiami.v6解密原理示例分析
    正文 JS加密是Web前端开发中常用的一种技术,可以用于保护敏感数据或者代码,避免被恶意攻击者窃取或篡改。其中,JS加密库JSJiami.v6是一款广受欢迎的JS加密库,下面我们...
    99+
    2023-05-16
    jsjiami.v6解密分析 jsjiami.v6 解密
  • OPENMP SECTIONS CONSTRUCT原理示例解析
    目录前言编译器角度分析动态库函数分析总结前言 在本篇文章当中主要给大家介绍 OpenMP 当中主要给大家介绍 OpenMP 当中 sections construct 的实现原理以...
    99+
    2023-03-06
    OPENMP SECTIONS CONSTRUCT OPENMP SECTIONS
  • gosyncOnce实现原理示例解析
    目录正文Once 的实现使用示例Once 的一些工作机制Once 详解hotpathatomic.LoadUint32atomic.StoreUint32Mutex总结正文 在很多...
    99+
    2023-01-03
    go sync Once实现原理 go sync.Once
  • 解析写jQuery能触发事件的内部原理
    在 Web 开发中,jQuery 的事件绑定有着非常重要的作用。它可以帮助开发者感知页面的各种入参变化,实现页面的实时交互。而要实现事件绑定,我们就需要了解其中的内部原理。那么,jQuery 能触发事件吗?接下来,我们就来一探究竟。jQue...
    99+
    2023-05-14
  • MySQL触发器是什么?原理与应用解析
    MySQL触发器是什么?原理与应用解析 MySQL触发器是一种存储过程,它会在指定的表中发生特定的操作(比如插入、更新、删除)时被自动执行。触发器可以用来监视和响应数据库中的数据变化,...
    99+
    2024-04-02
  • Nodejs高并发原理示例详解
    目录导读什么是事件循环事件循环详解每个循环阶段内容详解走进案例解析nextTick 与 setImmediatenextTick 递归的危害setImmediat...
    99+
    2022-11-13
    Nodejs高并发原理 Nodejs 高并发
  • MySQL示例DTID主从原理解析
    目录1.GTID基本概念2.GTID优点3.GTID的工作原理4.GTID比传统复制的优势5.启动的方法6.GTID(一主一从)配置6.1环境:6.2在主库上给从库授权:6.3确保数...
    99+
    2024-04-02
  • Label Propagation算法原理示例解析
    目录1. 概述2. Label Propagation算法2.1. Label Propagation算法概述2.2. Label Propagation算法原理3.3. Label...
    99+
    2023-02-01
    Label Propagation算法 Label Propagation
  • java LockSupport实现原理示例解析
    目录引言LockSupport常见函数LockSupport.parkLockSupport.unpark引言 前文中了解到AQS借助LockSupport.park和LockSup...
    99+
    2023-01-09
    java LockSupport原理 java LockSupport
  • react fiber执行原理示例解析
    目录为什么要使用fiber,要解决什么问题fiber是什么?数据结构执行单元浏览器工作:Fiber执行原理workInProgress tree:currentFiber tree:...
    99+
    2022-11-13
    react fiber执行原理 react fiber
  • Java并发中AQS原理的示例分析
    这篇文章给大家分享的是有关Java并发中AQS原理的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。线程阻塞原语Java 的线程阻塞和唤醒是通过 Unsafe 类的 park 和 unpark 方法做到的。...
    99+
    2023-06-02
  • Oracle触发器和游标的示例分析
    小编给大家分享一下Oracle触发器和游标的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!触发器:1、 创建一个用于记录用户操作的触发器  创建一个dep...
    99+
    2023-06-20
  • mysql触发器之创建多个触发器操作的示例分析
    这篇文章将为大家详细讲解有关mysql触发器之创建多个触发器操作的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。这次记录的内容mysql 版本必须得是5.7.2+...
    99+
    2024-04-02
  • 前端开发之CSS原理的示例分析
    这篇文章主要为大家展示了“前端开发之CSS原理的示例分析”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“前端开发之CSS原理的示例分析”这篇文章吧。  一、浏览器...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作