【译】Vue.set实际上是什么?

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

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


数据和响应式原理


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


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


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


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

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


image.png


可是,不,因为-


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会让你完全忘记这些边缘的案例,除了那些可怜的人儿,他们必须要针对某些不能完全支持新响应式系统的旧浏览器。



相关文章
|
JavaScript
VUE3(十三)main.ts中全局引入axios
VUE2中可以将我们需要的插件挂载到VUE的主链上(配置成全局属性),然后通过this调用,但是在VUE3的ts中使用这样的配置方法的话是没法通过编译的,这个时候我们就需要拓展属性。
1432 0
VUE3(十三)main.ts中全局引入axios
|
4月前
|
JavaScript
【Vue面试题八】、为什么data属性是一个函数而不是一个对象?
这篇文章解释了为什么在Vue中组件的`data`属性必须是一个函数而不是一个对象。原因在于组件可能会有多个实例,如果`data`是一个对象,那么这些实例将会共享同一个`data`对象,导致数据污染。而当`data`是一个函数时,每次创建组件实例都会返回一个新的`data`对象,从而确保了数据的隔离。文章通过示例和源码分析,展示了Vue初始化`data`的过程和组件选项合并的原理,最终得出结论:根实例的`data`可以是对象或函数,而组件实例的`data`必须为函数。
【Vue面试题八】、为什么data属性是一个函数而不是一个对象?
|
5月前
|
API
Vue2和Vue3的区别,OptionsAPI与CompositionAPI的区别,Vue2所有的数据,都写在data和method方法中,setup是一个全新的配置项,Vue2是选项式API的写法
Vue2和Vue3的区别,OptionsAPI与CompositionAPI的区别,Vue2所有的数据,都写在data和method方法中,setup是一个全新的配置项,Vue2是选项式API的写法
|
7月前
|
JavaScript
vue2中$set的原理_它对object属性做了啥?
vue2中$set的原理_它对object属性做了啥?
79 1
|
7月前
|
JavaScript
Vue中的v-if和v-show在性能上有何区别?
Vue中的v-if和v-show在性能上有何区别?
107 1
|
7月前
|
JavaScript 索引
Vue.set 方法原理
Vue.set 方法原理
42 0
|
7月前
|
JavaScript
Vue 中的 key 有什么作用
Vue 中的 key 有什么作用
36 0
|
7月前
|
JavaScript API
Vue.extend 作用和原理
Vue.extend 作用和原理
101 0
【Vue2.0学习】—el与data的两种写法(三十六)
【Vue2.0学习】—el与data的两种写法(三十六)
|
JavaScript
「Vue面试题」动态给vue的data添加一个新的属性时会发生什么?怎样去解决的?
「Vue面试题」动态给vue的data添加一个新的属性时会发生什么?怎样去解决的?
69 0