【译】Vue.set其实是什么?

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

数据和响应式原理

在一个Vue组件中,不管你什么时候建立一个data()功能属性,都会返回一个对象。Vue在组件背后作了不少事情,来使得它具备响应式。html

export default {
  data() {
   return {
     red: 'hot',
     chili: 'peppers'
   }
  }
}
复制代码

Vue要作的第一件事是使用咱们超帅的RHCP(Red Hot Chili Peppers, 一个超赞的乐队)data,它遍历了return {}对象的属性properties,而后为它们建立了惟一的gettersetter。具体状况已经超出了本文的范围,可是Vue Mastery有个很赞的视频去解析这点。vue

建立这些属性的目的是使你在代码中访问这些属性时(例如经过执行this.red或使用this.red=hotter进行设置时),其实是在调用Vue为你建立的gettersetterjava

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!(不胜则亡)

demo

但是,不,由于-

A. 这不是Orgrimmar(魔兽世界人物)

B. 如今咱们遇到问题了

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

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

实际使用Vue.set

因此,如今咱们明白问题实际出在哪里了,咱们能够学习什么是正确的解决方案。容许我向你介绍Vue.set

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

这彻底解决了咱们在另外一个例子中遇到的问题,由于当咱们设置member的新属性时,它将自动挂接到Vue的响应式系统中,酷酷的getters/settersVue的魔法都在框架背后运行。

可是,须要一点说明来了解它如何影响数组。到目前为止,咱们只是试验过了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

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

第二个参数是指向咱们传入第一个参数object/arraypropertykey(这里是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 )

可是数组的响应如何?

当咱们在最初的状态中建立一个arrayVue将它设置为响应式,然而,当你直接经过索引赋值,当前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

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

参考和后话

相关文章
相关标签/搜索