浅谈Vue.set实际上是什么


Posted in Javascript onOctober 17, 2019

谈到Vue.set就要说响应式原理,所以得为你自己准备下这方面的理论知识。然而,一如即往,这并不难或者枯燥。准备点鳄梨和薯条,制作些鳄梨酱,然后我们再进入话题。

数据和响应式原理

在一个Vue组件中,无论你何时创建一个data()功能属性,都会返回一个对象。Vue在组件背后做了很多事情,来使得它具有响应式。

export default {
 data() {
  return {
   red: 'hot',
   chili: 'peppers'
  }
 }
}

Vue要做的第一件事是使用我们超帅的RHCP(Red Hot Chili Peppers, 一个超赞的乐队)data,它遍历了return {}对象的属性properties,然后为它们创建了唯一的getter和setter。具体情况已经超出了本文的范围,但是Vue Mastery有个很赞的视频去解析这点。

创建这些属性的目的是使你在代码中访问这些属性时(例如通过执行this.red或使用this.red=hotter进行设置时),实际上是在调用Vue为你创建的getter和setter。

在SETGET这块神奇的土地上,Vue连接起了computer properties, watchers, props,data等,从而变得响应式。以非常简单的方式,它被称为一个函数,该函数在每次setter改变时更新整个工作。

陷阱

酷极了!这就是我们喜欢Vue的原因,它具有响应式和强大的幕后功能。但是也有一些阴暗面需要我们探讨。

在我们开始之前,我们更改下data数据看发生什么。

data() {
  return {
    members: {}
  }
}

好吧,到目前为止没什么看头,我们在data中有一个member属性,用来添加乐队成员的信息。现在,为了举例,我们添加一个方法,并假装从远程http请求中拉取一些信息,它将返回一个乐队信息的JSON对象。

data() {
 return {
  members: {}
 }
},
methods: {
 getMembers() {
  const newMember = {
   name: 'Flea',
   instrument: 'Bass',
   baeLevel: 'A++'
  }; // Some magical method that gives us data got us this sweet info

  // ...
 }
}

嗯。好吧,我们先停停然后思考下这个例子。如何将newMember对象添加到当前的member属性中?这有许多方法可以解决当前的难题。

也许你会想,我们可以将member转换成一个数组,然后将它push进去。这可行,但是这是在作弊,因为它破坏了我开始输入时细心构造的例子。

在这种情况下,我们member是一个object。好吧,简单,你会说,我们在member上添加一新的属性,这样它还是一个object。实际上,我们在member上添加个name属性。

getMembers() {
  const newMember = {
   name: 'Flea',
   instrument: 'Bass',
   baeLevel: 'A++' // Totally important property that we will never use
  }; // Some magical method that gives us data got us this sweet info

  this.members[newMember.name] = newMember;
 }

Lok'tar Ogar!(不胜则亡)

可是,不,因为-

A. 这不是Orgrimmar(魔兽世界人物)
B. 现在我们遇到问题了

如果你在浏览器上测试这段代码,你将看到你确实将新数据推入member数据中了,但是此次的更改组件的状态将不会使得你的应用重新渲染。

仅将这些数据用于某些计算或某种内部存储的情况下,以这种方式进行操作不会影响你的应用程序。然而,这里应该是大大的转折HOWERVER,如果你在自己app上正在使用这种数据去展示数据,或者根据条件v-if或v-else来渲染,事情将变得有趣。

实际使用Vue.set

所以,现在我们明白问题实际出在哪里了,我们可以学习什么是正确的解决方案。允许我向你介绍Vue.set。

Vue.set是一个工具,它允许我们向已经激活的对象添加新属性,然后确保这个新的属性也是响应的。

这完全解决了我们在另一个例子中遇到的问题,因为当我们设置member的新属性时,它将自动挂接到Vue的响应式系统中,酷酷的getters/setters和Vue的魔法都在框架背后运行。

但是,需要一点说明来了解它如何影响数组。到目前为止,我们只是试验过了objects,这很容易理解。新的属性?如果你希望它是响应式,则通过Vue.set添加。简单~

延续上面的示例,我们切换为使用Vue.set的方式。

getMembers() {
  const newMember = {
   name: 'Flea',
   instrument: 'Bass',
   baeLevel: 'A++'
  }; // Some magical method that gives us data got us this sweet info

  //this.members[newMember.name] = newMember;
   this.$set(this.members, newMember.name, newMember);
 }

这是新添加的this.$set(this.members, newMember.name, newMember);。

对于这段代码,我有两点想提下。目前为止,我告诉了你Vue.set是怎样工作的,但是现在我使用this.$set,但是不要担心,这只是个别名,所以它会以完全相同的方式运行。比较酷的是你不用在你的组件中引入Vue。

我想说的第二点是这个函数的语法。它需要传入三个参数,第一个参数是我们要改变的object或array(案例上是this.members)。

第二个参数是指向我们传入第一个参数object/array的property或key(这里是newMember.name,因为我们想动态生成)。
最后是第三个参数,它是我们想要设置的值(在案例中,newMember)。

this.members [newMember.name] = newMember;
//      V        V       V
this.$set(this.members, newMember.name,  newMember);

(PS. My ASCII skills are not for sale )

但是数组的响应如何?

当我们在最初的状态中创建一个array,Vue将它设置为响应式,然而,当你直接通过索引赋值,当前Vue不能检测到。例如,我们如下操作:

this.membersArray[3] = myNewValue;

然而,Vue不能检测到这种更改,因此它不是响应式的。请铭记于心,如果你通过pop,splice,push操作来更改数组,那么这些操作将触发数组的响应式,所以你可以安全地使用它们。

在必要的时候我们需要直接通过索引赋值,我们可以使用Vue.set。我们看下它和之前的例子有什么区别。

this.$set(this.membersArray, 3, myNewValue)

如果你想了解更多响应式原理的注意点,请移步[link to the official documentation](https://vuejs.org/v2/guide/list.html#Caveats) 。

Vue 3.0

在编写这篇文章时,这一切仍然可能更改,但是现在满大街都在说这些警告将不再是问题。换言之,Vue 3.0会让你完全忘记这些边缘的案例,除了那些可怜的人儿,他们必须要针对某些不能完全支持新响应式系统的旧浏览器。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Javascript中的数学函数
Apr 04 Javascript
jQuery 使用手册(一)
Sep 23 Javascript
javascript Keycode对照表
Oct 24 Javascript
Jquery创建一个层当鼠标移动到层上面不消失效果
Dec 12 Javascript
js判断iframe内的网页是否滚动到底部触发事件
Mar 18 Javascript
js获取鼠标点击的位置实现思路及代码
May 09 Javascript
5款JavaScript代码压缩工具推荐
Jul 07 Javascript
无需 Flash 使用 jQuery 复制文字到剪贴板
Apr 26 Javascript
纯js实现倒计时功能
Jan 06 Javascript
security.js实现的RSA加密功能示例
Jun 06 Javascript
关于layui 下拉列表的change事件详解
Sep 20 Javascript
vuex存取值和映射函数使用说明
Jul 24 Javascript
Vuex modules模式下mapState/mapMutations的操作实例
Oct 17 #Javascript
vuex + keep-alive实现tab标签页面缓存功能
Oct 17 #Javascript
Weex开发之地图篇的具体使用
Oct 16 #Javascript
WEEX环境搭建与入门详解
Oct 16 #Javascript
Weex开发之WEEX-EROS开发踩坑(小结)
Oct 16 #Javascript
适合前端Vue开发童鞋的跨平台Weex的使用详解
Oct 16 #Javascript
微信公众号开发之微信支付代码记录的实现
Oct 16 #Javascript
You might like
比较简单实用的PHP无限分类源码分享(思路不错)
2011/10/13 PHP
php使用exec shell命令注入的方法讲解
2013/11/12 PHP
ThinkPHP自动转义存储富文本编辑器内容导致读取出错的解决方法
2014/08/08 PHP
php实现基于微信公众平台开发SDK(demo)扩展的方法
2014/12/22 PHP
CodeIgniter开发实现支付宝接口调用的方法示例
2016/11/14 PHP
PHP CodeIgniter分页实例及多条件查询解决方案(推荐)
2017/05/20 PHP
ThinkPHP实现的rsa非对称加密类示例
2018/05/29 PHP
php实现的支付宝网页支付功能示例【基于TP5框架】
2019/09/16 PHP
YII2框架使用控制台命令的方法分析
2020/03/18 PHP
input 输入框内的输入事件详细分析
2010/03/17 Javascript
基于Jquery的文字滚动跑马灯插件(一个页面多个滚动区)
2010/07/26 Javascript
js arguments对象应用介绍
2012/11/28 Javascript
jquery实现textarea输入字符控制(仿微博输入控制字符)
2013/04/26 Javascript
深入理解Javascript中this的作用域
2014/08/12 Javascript
jquery实现的美女拼图游戏实例
2015/05/04 Javascript
js变形金刚文字特效代码分享
2015/08/20 Javascript
jquery图片滚动放大代码分享(1)
2015/08/25 Javascript
jQuery Ajax和getJSON获取后台普通json数据和层级json数据用法分析
2016/06/08 Javascript
[原创]javascript typeof id==='string'?document.getElementById(id):id解释
2016/11/02 Javascript
bootstrapValidator自定验证方法写法
2016/12/01 Javascript
jQuery扇形定时器插件pietimer使用方法详解
2017/07/18 jQuery
JavaScript模拟文件拖选框样式v1.0的实例
2017/08/04 Javascript
JQuery实现table中tr上移下移的示例(超简单)
2018/01/08 jQuery
vue键盘事件点击事件加native操作
2020/07/27 Javascript
栈和队列数据结构的基本概念及其相关的Python实现
2015/08/24 Python
python爬虫爬取淘宝商品信息
2018/02/23 Python
PyTorch中Tensor的维度变换实现
2019/08/18 Python
解决pycharm编辑区显示yaml文件层级结构遇中文乱码问题
2020/04/27 Python
html5 canvas-1.canvas介绍(hello canvas)
2013/01/07 HTML / CSS
美国保健品专家:Life Extension
2018/05/04 全球购物
美国最大的存储市场:SpareFoot
2018/07/23 全球购物
毕业生个人求职信范例分享
2013/12/17 职场文书
商场端午节活动方案
2014/01/29 职场文书
2015中学教师个人工作总结
2015/07/22 职场文书
MySQL通过binlog恢复数据
2021/05/27 MySQL
宫崎骏十大动画电影,宫崎骏好看的动画电影排名
2022/03/22 日漫