浅谈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 相关文章推荐
jquery js 重置表单 reset()具体实现代码
Aug 05 Javascript
JS控制一个DIV层在指定时间内消失的方法
Feb 17 Javascript
使用three.js 画渐变的直线
Jun 05 Javascript
JavaScript动态检验密码强度的实现方法
Nov 09 Javascript
浅谈jQuery中的$.extend方法来扩展JSON对象
Feb 12 Javascript
AngularJS中的promise用法分析
May 19 Javascript
js 图片转base64的方式(两种)
Apr 24 Javascript
超出JavaScript安全整数限制的数字计算BigInt详解
Jun 24 Javascript
JS中async/await实现异步调用的方法
Aug 28 Javascript
基于Element封装一个表格组件tableList的使用方法
Jun 29 Javascript
基于 Vue 的 Electron 项目搭建过程图文详解
Jul 22 Javascript
深入浅析React中diff算法
May 19 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 面向对象程序设计(oop)学习笔记 (二) - 静态变量的属性和方法及延迟绑定
2014/06/12 PHP
将酷狗krc歌词解析并转换为lrc歌词php源码
2014/06/20 PHP
PHP 使用memcached简单示例分享
2015/03/05 PHP
phpMyAdmin安装并配置允许空密码登录
2015/07/04 PHP
PHP实现上传文件并存进数据库的方法
2015/07/16 PHP
基于CI(CodeIgniter)框架实现购物车功能的方法
2018/04/09 PHP
浅谈PHP匿名函数和闭包
2019/03/08 PHP
JS类的封装及实现代码
2009/12/02 Javascript
jquery+json 通用三级联动下拉列表
2010/04/19 Javascript
JavaScript 实现类的多种方法实例
2013/05/01 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战一)
2013/08/21 Javascript
JavaScript中获取样式的原生方法小结
2014/10/08 Javascript
基于Node.js的强大爬虫 能直接发布抓取的文章哦
2016/01/10 Javascript
javascript中利用柯里化函数实现bind方法【推荐】
2016/04/29 Javascript
jQuery DataTables插件自定义Ajax分页实例解析
2020/04/28 Javascript
JS脚本实现动态给标签控件添加事件的方法
2016/06/02 Javascript
去掉vue 中的代码规范检测两种方法(Eslint验证)
2018/03/21 Javascript
JS实现同一DOM元素上onClick事件与onDblClick事件并存的解决方法
2018/06/07 Javascript
Node.js 进程平滑离场剖析小结
2019/01/24 Javascript
Python实现的简单模板引擎功能示例
2017/09/02 Python
Python实现连接两个无规则列表后删除重复元素并升序排序的方法
2018/02/05 Python
Python实现的朴素贝叶斯算法经典示例【测试可用】
2018/06/13 Python
Python 中pandas索引切片读取数据缺失数据处理问题
2019/10/09 Python
python3中datetime库,time库以及pandas中的时间函数区别与详解
2020/04/16 Python
python不到50行代码完成了多张excel合并的实现示例
2020/05/28 Python
世界上最值得信赖的多日游在线市场:TourRadar
2018/07/20 全球购物
英国第一的滑雪服装和装备零售商:Snow+Rock
2020/02/01 全球购物
初中校园广播稿
2014/02/02 职场文书
党员对照检查材料思想汇报
2014/09/16 职场文书
2014年向国旗敬礼活动总结
2014/09/27 职场文书
社区领导班子四风问题原因分析及整改措施
2014/09/28 职场文书
2014年机关作风建设工作总结
2014/10/23 职场文书
加强作风建设工作总结
2014/10/23 职场文书
民主评议党员个人自我评价
2015/03/03 职场文书
物业项目经理岗位职责
2015/04/01 职场文书
在校证明模板
2015/06/17 职场文书