vue中$set用法及其源码的底层原理

news/2024/7/10 3:25:45 标签: vue, js, javascript

vueset_0">vue中$set用法及其源码的底层原理

在我们开发过程中,经常会遇到,为一个数组或者对象data中添加一个属性,点击按钮后发现,控制台打印明明对象中已经出现了这个属性,视图层却并没有更新该数据,这是因为受到JS的限制,vue.js中不能监听对象属性的添加和删除,因为在vue组件初始化过程中,会调用getter和setter方法,所以该属性只有存在data中时,试图层才会响应数据的变化。

当我们对对象属性进行添加和删除的操作时,或者数组通过索引去修改值时都不会触发vue的响应式原理,导致视图并不会渲染,数据也不会并不会改变,这个时候就要使用到$set

解决办法:
(1)通过 s e t 对 象 中 : t h i s . set 对象中:this. setthis.set(obj,key,value)

javascript">	student: {
	name:'张三',
	age:16
}
点击事件中:
changeStudent() {
	this.$set(this.student, 'name', '陈皮阿四')
}
console.log(this.student)	//{name:'陈皮阿四',age:16}

数组中:this.$set(obj,index,value)

javascript">	student: [1,2,3,'chen']
点击事件中:
changeStudent() {
	this.$set(this.student, 1, 'chenchen')
}
console.log(this.student)	//['chenchen',2,3,'chen']

(2)通过Object.assign(target, sources)方法

javascript">student: {
	name:'张三',
	age:16
}
点击事件中:
changeStudent() {
	this.student.name='陈皮阿四'
	this.student = Object.assign({}, this.student)
	console.log(this.student)	// {name:'陈皮阿四',age:16}
}

我们通过这两种方法为对象添加属性之后,他的对象上就多了set和get方法,再次操作属性的时候,就会引起视图的更新了

js">$set的源码分析
通过传入target,key,value三个值,首先通过isArray判断target是否是数组,是的话则比较key与当前数组
长度的最大值作为数组新长度,然后通过数组splice方法将传入key对应的val值添加进新数组;如果传入的不是
数组则被当做对象处理,通过in方法判断key是否存在target中,如果存在则只是普通的修改值,如果不存在则
说明是对对象属性值的添加或者删除,我们此时要去判断target的__ob__属性,如果为false则说明不是响应式,
只需要简单为他添加上新的属性,如果为true的话则说明是响应式,我们就需要通过defineReactive(将新属
性添加完后转为响应式)将新熟悉添加到target上,最后通知依赖进行更新

 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
}

http://www.niftyadmin.cn/n/884544.html

相关文章

矩阵分解(2)--- 奇异值分解(SVD),AX=b问题

1. 特征值与特征向量 2. SVD奇异值分解 2.1 SVD定义 wiki: https://zh.wikipedia.org/wiki/%E5%A5%87%E5%BC%82%E5%80%BC%E5%88%86%E8%A7%A3 2.2 SVD理解 Ref:奇异值分解(SVD) - 知乎 应用: 对于齐次线性方程 A*X…

震惊!!!一眼就能看懂的setAttribute用法!!!!

setAttribute(String(添加属性名称),String(添加属性值)) 方法添加指定的属性,并为其赋指定的值,如果指定属性存在,则仅设置/更改值 例子1:var a document.querySelector("button") a.setAttribute("…

震惊!!!一眼就能看懂的getBoundingClientRect用法!!!

主要介绍getBoundingClientRect的基本属性,以及具体的使用场景和一些需要注意的问题。 getBoundingClientRect Element.getBoundingClientRect() 含义: 方法返回元素的大小及其相对于视口的位置。 值: 返回值是一个 DOMRect 对象&#xff0…

vue中scss从安装到最后完成一键换肤效果全过程

本来打算用less来实现这个功能,更为轻量简便,但是平时scss使用更多,首先是安装scss 一、安装对应依赖node模块:npm install node-sass --save-devnpm install sass-loader --save-dev二、 在vue.config.js中进行配置module.export…

ROS学习笔记 -- IMU in ROS

目录 1. IMU简介 2. ROS IMU msgs 3. 创建IMU消息发布节点node 4. 小结 查看电脑链接的串口信息(名称): dmesg | grep ttyS* 1. IMU简介 请移步本人的另一篇博客文章,详细介绍了IMU工作原理和卡尔曼滤波方法:http…

干货--项目中封装好的防抖节流方法

为什么需要防抖节流: 开发中经常容易遇到一些持续发生的事件,比如scroll, resize, input, mousemove等,频繁的执行回调,造成页面性能的损耗,页面容易卡死,这时候就有两种解决方法,防抖和回流 防…

ROS学习笔记 使用imu_tools对imu_raw数据进行滤波和可视化

目录 1 前言 2. 安装 From source files 3. IMU原始数据测试 3.1 文件系统 注:遇到串口权限问题,请安装此步骤解决 3.2 运行imu_read_node 运行节点launch文件 查看节点和话题信息 查看原始数据: 3.3 打开rviz查看原始的imu数据 …

世界坐标系前端分类

世界坐标系有哪些分类 世界坐标系是依据笛卡尔右手坐标系来确定图形中的各点位置,X轴为水平方向,Y轴为垂直方向,Z轴为垂直于XY平面的方向,远点O的坐标为(0,0,0)。世界坐标系是一个固定不变的坐标系&#xf…