谈到Vue.set
就要说响应式原理,因此得为你本身准备下这方面的理论知识。然而,一如即往,这并不难或者枯燥。准备点鳄梨和薯条,制做些鳄梨酱,而后咱们再进入话题。javascript
在一个Vue
组件中,不管你什么时候建立一个data()
功能属性,都会返回一个对象。Vue
在组件背后作了不少事情,来使得它具备响应式。html
export default {
data() {
return {
red: 'hot',
chili: 'peppers'
}
}
}
复制代码
Vue
要作的第一件事是使用咱们超帅的RHCP(Red Hot Chili Peppers, 一个超赞的乐队)data
,它遍历了return {}
对象的属性properties
,而后为它们建立了惟一的getter
和setter
。具体状况已经超出了本文的范围,可是Vue Mastery有个很赞的视频去解析这点。vue
建立这些属性的目的是使你在代码中访问这些属性时(例如经过执行this.red
或使用this.red=hotter
进行设置时),其实是在调用Vue
为你建立的getter
和setter
。java
在SETGET
这块神奇的土地上,Vue
链接起了computer properties, watchers, props,data
等,从而变得响应式
。以很是简单的方式,它被称为一个函数,该函数在每次setter
改变时更新整个工做。react
酷极了!这就是咱们喜欢Vue
的缘由,它具备响应式和强大的幕后功能。可是也有一些阴暗面须要咱们探讨。git
在咱们开始以前,咱们更改下data
数据看发生什么。github
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
是一个工具,它容许咱们向已经激活的对象添加新属性,而后确保这个新的属性也是响应的。
这彻底解决了咱们在另外一个例子中遇到的问题,由于当咱们设置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](vuejs.org/v2/guide/li…)。
在编写这篇文章时,这一切仍然可能更改,可是如今满大街都在说这些警告将再也不是问题。换言之,Vue 3.0
会让你彻底忘记这些边缘的案例,除了那些可怜的人儿,他们必需要针对某些不能彻底支持新响应式系统的旧浏览器。