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

数组监测案例

image

image

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

  • 加上this.$forceUpdate(),页面更新。
  • 也可以直接用vm.$set()或给items重新赋值或用数组方法,如下:


    image
  • 再来看个神奇的操作【这里应该涉及到diff算法、VNODE,另行学习】
    image

    将修改按钮的函数改成如上图,这时候点击修改按钮
    image

    this.items[1] = {message:'See'}这句也一起起效了哦!

数组(或对象)更新检测

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

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 不能检测以下数组的变动(可以参看文首案例):

  • 当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue
  • 当你修改数组的长度时,例如:vm.items.length = newLength(可以用splice
  • 好好看下第一个案例,各种使它生效的方法

对象变更检测注意事项

image

image
  • 点击修改按钮,页面没有变化(upt方法加一句this.user.sex='女'页面会变化,两个属性改变都生效,和数组一个意思)
  • 还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:
var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的
vm.b = 2
// `vm.b` 不是响应式的
  • 对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, propertyName, value)(vm.$set) 方法向嵌套对象添加响应式属性
  • 有时你可能需要为已有对象赋值多个新属性,比如使用 Object.assign()_.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:
Object.assign(vm.userProfile, {
  age: 27,
  favoriteColor: 'Vue Green'
})

你应该这样做:

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

列表渲染v-for

image
  • 新版本key不要少
  • index:当前项的索引
  • 可以用 of 替代 in 作为分隔符
<div v-for="item of items"></div>
  • 你也可以用 v-for 来遍历一个对象的属性
<!--
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
  • 显示过滤/排序后的结果

    有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。

    image

    在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法:
    image

    计算属性和侦听器

计算属性缓存 vs 方法
我们可以将同一函数定义为一个方法而不是一个计算属性。
两种方式的最终结果确实是完全相同的。
然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。
只在相关响应式依赖发生改变时它们才会重新求值。
这就意味着只要 message 还没有发生改变,
多次访问 reversedMessage 计算属性会立即返回之前的计算结果,
而不必再次执行函数。

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

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

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

计算属性 vs 侦听属性
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。
当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch——
特别是如果你之前使用过 AngularJS。
然而,通常更好的做法是使用计算属性而不是命令式的 watch 回调。
  • v-for 也可以接受整数
<span v-for="n in 10">{{ n }} </span>
  • 不推荐在同一元素上使用 v-ifv-for
<!--
当它们处于同一节点,`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维护状态(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 不存在的元素。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容

  • vue概述 在官方文档中,有一句话对Vue的定位说的很明确:Vue.js 的核心是一个允许采用简洁的模板语法来声明...
    li4065阅读 7,185评论 0 25
  • 主要还是自己看的,所有内容来自官方文档。 介绍 Vue.js 是什么 Vue (读音 /vjuː/,类似于 vie...
    Leonzai阅读 3,327评论 0 25
  • Vue 实例 属性和方法 每个 Vue 实例都会代理其 data 对象里所有的属性:var data = { a:...
    云之外阅读 2,198评论 0 6
  • 1. Vue 实例 1.1 创建一个Vue实例 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实...
    王童孟阅读 1,014评论 0 2
  • 一、了解Vue.js 1.1.1 Vue.js是什么? 简单小巧、渐进式、功能强大的技术栈 1.1.2 为什么学习...
    蔡华鹏阅读 3,311评论 0 3