vue的双向绑定原理_vue2双向绑定原理

vue的双向绑定原理_vue2双向绑定原理1、背景今天要讲的内容是Web前端框架vue.js中的一个细节,注意是细节哦,稍不留神就掉坑里了。由于这两天在公司开发前端vue页面,踩到了一个坑,这个坑不大不小的,但是对于我这种除非公司需要,否则不会主动学习前端技术的后端开发者来说,这个坑困扰了我半天时间。无论怎么修改代码,还是实现不了效果,归根结底还是没有找到问题的点所在。凡事都有好的一面,今天上午脑子就开了光,思路比昨天下午清晰多了,顺着思路,我终于发现了问题的点所在,然后百度一搜,果然是这样,嗨!于是我决定总结一番!大家都知道,vu

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

1、背景

今天要讲的内容是Web前端框架vue.js中的一个细节,注意是细节哦,稍不留神就掉坑里了。

由于这两天在公司开发前端vue页面,踩到了一个坑,这个坑不大不小的,但是对于我这种除非公司需要,否则不会主动学习前端技术的后端开发者来说,这个坑困扰了我半天时间。无论怎么修改代码,还是实现不了效果,归根结底还是没有找到问题的点所在。

凡事都有好的一面,今天上午脑子就开了光,思路比昨天下午清晰多了,顺着思路,我终于发现了问题的点所在,然后百度一搜,果然是这样,嗨!于是我决定总结一番!

大家都知道,vue的核心特性是数据动态双向绑定,但是数据绑定背后的原理是什么呢,这个有必要了解一番。

2、VUE核心原理

当你将一个普通的js对象作为vue的数据时,vue会遍历该对象的所有属性,并通过Object.defineProperty()方法将这些属性全部转化为getter/setter。defineProperty()是js标准内置对象Object的一个方法,用于直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。这句话有点抽象,先来看一下该方法的语法。

2.1、Object.defineProperty()

Object.defineProperty(obj, prop, descriptor)
  • obj:对象

  • prop:对象的某个属性

  • descriptor:属性描述符

属性描述符有以下可选方案:

  • configurable:当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除,默认为 false

  • enumerable:当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中,默认为 false

  • value:该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等),默认为 undefined

  • writable:当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符改变,默认为 false

  • get:属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值,默认为 undefined

  • set:属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象,默认为 undefined

通过上面的介绍,我们了解到了Object.defineProperty()方法可以这么用。

Object.defineProperty(user, "name", {get() { return value; },  set(newValue) { value= newValue; },  configurable : true,  value: "小明"  });

关于Object.defineProperty()更深层次的介绍请戳这里 Object.defineProperty() – JavaScript | MDN

2.2、组件渲染

Object.defineProperty()说完了,接下来继续聊聊vue的响应式原理。前面说到Object.defineProperty()方法将这些属性全部转化为getter/setter,而这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property 被访问和修改时通知变更。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的 setter 触发时,会通知 watcher,从而使它关联的组件重新渲染。这种关系可以用下图表示。

vue的双向绑定原理_vue2双向绑定原理

3、脱坑关键

说完了上面的vue核心原理,下面聊聊标题:vue不能动态监测对象属性的问题!

由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。一听到这,是不是觉得没法玩了?不要慌,问题总是有解决办法滴!下面就聊聊解决办法!

3.1、对于对象

Vue 无法检测 property的添加或移除。由于 Vue 会在初始化实例时对 property 执行 getter/setter 转化,所以 property 必须在对象上存在才能让 Vue 将它转换为响应式的。例如:

对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如:

var vm = new Vue({
  data:{
    a:1
  }
});
//vm.a是响应式的

vm.b = 2
//vm.b是非响应式的

对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式 property。例如:

Vue.set(vm.someObject, 'b', 2)

您还可以使用 vm.$set 实例方法,这是全局 Vue.set 方法的别名:

this.$set(this.someObject,'b',2)

3.2、对于数组

Vue 不能检测以下数组的变动:

  • 当你利用索引直接设置一个数组项时,例如:vm.array[index] = newValue

  • 当你修改数组的长度时,例如:vm.array.length = newLength

举个栗子:

var vm = new Vue({

  data: {
    array: ['a', 'b', 'c']
  }
});

vm.array[1] = 'x' //不是响应性的
vm.array.length = 2 //不是响应性的

为了解决第一类问题,以下三种方式都可以实现和 vm.array[index] = newValue 相同的效果,同时也将在响应式系统内触发状态更新:

// Vue.set
Vue.set(vm.array, index, newValue)

// Array.prototype.splice
vm.array.splice(index, 1, newValue)

//vm.$set
vm.$set(vm.array, index, newValue)

为了解决第二类问题,你可以使用 splice:

vm.array.splice(newLength)

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/180726.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • java 继承是什么_java中继承指的是什么

    java 继承是什么_java中继承指的是什么java中继承指的是什么发布时间:2020-08-2014:46:11来源:亿速云阅读:55作者:小新这篇文章将为大家详细讲解有关java中继承指的是什么,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。java中继承是什么?Java中的继承是一个对象获取父对象的所有属性和行为的机制。它是面向对象编程系统(OOP)的重要组成部分。Java中继承的思想是,创建基于现…

  • RabbitMQ流控-FLow Control

    RabbitMQ流控-FLow Control当Connection发布消息的速度太快,队列无法跟上(消费速度低于生产速度),RabbitMQ会降低Connection的速度,无需配置。流控的Connection可以在rabbitmqctl、管理UI和HTTPAPI响应中显示flow状态。这意味着连接每秒要经历多次阻塞和解除阻塞,以便将消息传入的速度保持在服务器其他部分(例如,将这些消息路由到的队列)能够处理的速度。一般来说,处于流…

  • Hostapd Android[通俗易懂]

    Hostapd Android[通俗易懂]HostapdAndroidhttps://github.com/lnmcc/hostapd-android http://www.omitol.com/archives/109.html http://forum.xda-developers.com/showthread.php?t=1988735 http://droidmodderx.com/galaxyn…

  • IDM下载百度网盘文件,获取百度网盘文件url地址,激活成功教程

    IDM下载百度网盘文件,获取百度网盘文件url地址,激活成功教程下面是谷歌插件,你用这个里面的谷歌进入百度网盘,会有一个显示百度网盘文件链接选项,复制这个链接到IDM就可以了。链接:https://pan.baidu.com/s/1B0C-VyWvf7xc5Y1kcpKr9g提取码:bn6q复制这段内容后打开百度网盘手机App,操作更方便哦网速只是比平常快一些,但并不能全速。…

  • substring() 方法用于提取字符串中介于两个指定下标之间的字符。

    substring() 方法用于提取字符串中介于两个指定下标之间的字符。

    2021年10月30日
  • Sqlserver DateTime转换成SMALLDATETIME时“产生一个超出范围的值”「建议收藏」

    Sqlserver DateTime转换成SMALLDATETIME时“产生一个超出范围的值”「建议收藏」工作中遇到一个问题,A表中字段(DateTime1)的数据类型为DateTime,新建了一张表B的SMALLDATETIME1字段的数据来自A表的DateTime1但在将A表字段DateTime1导出到B表的SMALLDATETIME1字段时出现了以下错误后经过排查发现在原来是A表DateTime1字段的值有许多是"1753-01-0100:00:00.000",从而导致转换失败…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号