【vue学习】数组/对象更新监测

2019-08-10  本文已影响0人  前端菜篮子

数组监测案例

image
image
点击修改,页面未变化,查看控制台打印信息(items是最新数据):
image

数组(或对象)更新检测

直接调用数组方法触发更新

Vue 将被侦听的数组的变异方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:push()pop()shift()unshift()splice()sort()reverse()。如上述案例中调用:

this.items.pop() //删除最后一个元素
this.items.push({message:'See'})//新增一个元素

点击修改按钮,执行上述代码,页面即可更新。

替换数组(数组重新赋值)

上述案例可以直接用如下代码,页面即可更新:

this.items= [
    { message: 'Foo' },
    { message: 'See' }
] 

数组中有些方法执行后,原数组不会发生变化, 如filter()concat()slice() 。它们不会改变原始数组,而总是返回一个新数组。当调用这些方法(非变异方法)时,可以用新数组替换旧数组

this.items = this.items.filter(function (item) {
  return item.message.match(/Foo/)
})

你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。Vue 为了使得 DOM 元素得到最大范围的重用而实现了一些智能的启发式方法,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

数组更新的注意事项

由于 JavaScript 的限制,Vue 不能检测以下数组的变动(可以参看文首案例):

对象变更检测注意事项

image
image
var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

你应该这样做:

vm.userProfile = Object.assign({}, vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

列表渲染v-for

image
<div v-for="item of items"></div>
<!--
object: {
  title: 'How to do lists in Vue',
  author: 'Jane Doe',
  publishedAt: '2016-04-10'
}
-->
<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
<!--
value:键值, name:键名 , index:索引
<div v-for="(value, name, index) in object" :key="index">name</div>
-->
image
计算属性缓存 vs 方法
我们可以将同一函数定义为一个方法而不是一个计算属性。
两种方式的最终结果确实是完全相同的。
然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。
只在相关响应式依赖发生改变时它们才会重新求值。
这就意味着只要 message 还没有发生改变,
多次访问 reversedMessage 计算属性会立即返回之前的计算结果,
而不必再次执行函数。

这也同样意味着下面的计算属性将不再更新,
因为 Date.now() 不是响应式依赖:

computed: {
  now: function () {
    return Date.now()
  }
}
相比之下,每当触发重新渲染时,
调用方法将总会再次执行函数。

我们为什么需要缓存?
假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。
然后我们可能有其他的计算属性依赖于 A 。
如果没有缓存,我们将不可避免的多次执行 A 的 getter!
如果你不希望有缓存,请用方法来替代。

计算属性 vs 侦听属性
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。
当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——
特别是如果你之前使用过 AngularJS。
然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。
<span v-for="n in 10">{{ n }} </span>
<!--
当它们处于同一节点,`v-for` 的优先级比 `v-if` 更高,
这意味着 `v-if` 将分别重复运行于每个 `v-for` 循环中。

而如果你的目的是有条件地跳过循环的执行,
那么可以将 v-if 置于外层元素 (或 <template>)上。如:
-->
<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>

v-for维护状态(v-for循环中key有什么作用)

  1. Vue正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染
  2. 这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
  3. 为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性:
<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>
  1. 建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
  2. 因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。
  3. 不要使用对象或数组之类的非基本类型值作为 v-forkey。请用字符串或数值类型的值。
  4. 更多 key attribute 的细节用法请移步至 key 的 API 文档
  5. key 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes
  6. 如果不使用 keyVue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
上一篇 下一篇

猜你喜欢

热点阅读