7. 列表渲染

v-for 指令 — 数组

  1. v-for 指令基于一个数组来渲染一个列表
  2. 使用 item in items(item, index) in items形式的特殊语法
  3. items是源数据数组, item 是被迭代的数组元素的别名
<ul id="example-2">
  <li v-for="(item, index) in items">
    {{ parentMessage }} - {{ index }} - {{ item.message }}
  </li>
</ul>
var example2 = new Vue({
  el: '#example-2',
  data: {
    parentMessage: 'Parent', // v-for 可直接访问
    items: [
      { message: 'Foo' }, //数组内对象为被迭代的item
      { message: 'Bar' }
    ]
  }
})
  • v-for块中,可以访问所有父作用域的属性

  • 可用 of 替代in 作为分隔符

维护状态-key

  1. 当 Vue 正在更新使用 v-for 渲染的元素列表时,默认使用“就地更新”的策略
  2. 只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出
  3. 为每项提供一个唯一 key 属性,便于跟踪每个节点的身份,从而重用和重新排序现有元素
<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>
  • 不要使用对象或数组之类的非基本类型值作为 v-forkey

数组更新检测

变异方法 (mutation method)

  1. Vue 将被侦听的数组的变异方法进行了包裹,变异方法将会触发视图更新
  2. 改变调用了变异方法的原始数组
  • push()——接收任意数量的参数,把逐个添加到数组末尾,并返回修改后数组的长度
  • pop()——从数组末尾移除后一项,减少数组的 length 值,返回移除的项
  • shift()——移除数组中的第一个项并返回该项,同时将数组长度减 1
  • unshift()——能在数组前端添加任意个项并返回新数组的长度
  • splice()——向数组的中部插入项(删除项的起始位置、删除的项数、插入任意数量的项)
  • sort()——按升序排列数组项,可以接收一个比较函数作为参 数
  • reverse()——反转数组项的顺序

替换数组

  1. 不会改变原始数组,而总是返回一个新数组
  2. 当使用非变异方法时,可以用新数组替换旧数组
example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})
  • filter()
  • concat()
  • slice()

注意事项

由于 JavaScript 的限制,Vue 不能检测以下数组的变动,在界面为非响应式

  1. 利用索引直接设置一个数组项时

    vm.items[2] = 'newValue'
    
  2. 修改数组的长度时

    vm.items.length = 3
    

解决问题

vm.items[indexOfItem] = newValue

方式一:

// Vue.set
Vue.set(vm.items, indexOfItem, newValue)
vm.$set(vm.items, indexOfItem, newValue)  //vm.$set 实例方法
Vue.set(items, 2, '响应式新值')

方式二:

// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
vm.items.splice(2, 1, '响应式新值')

vm.items.length = newLength

vm.items.splice(newLength)
vm.items.splice(3)

v-for 指令 — 对象

  1. v-for 来遍历一个对象的属性
  2. 使用 value in object(value, name, index) in object形式的特殊语法
<div v-for="(value, name, index) in object">
  键名-{{ value}}
  键值-{{ name }}
  索引-{{ index}}
</div>
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2019-10-25'
    }
  }
})
  • 在遍历对象时,会按 Object.keys() 的结果遍历

对象变更检测

注意事项

由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除

  1. 对于已经创建的实例,Vue 不允许动态添加根级别的响应式属性

解决方法

Vue.set(object, propertyName, value) 方法向嵌套对象添加响应式属性

添加单个属性

Vue.set(vm.userProfile, 'age', 27)

添加多个属性

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

显示过滤/排序后的结果

  1. 显示一个数组经过过滤或排序后的版本,而不实际改变或重置原始数据

    计算属性

    <li v-for="n in evenNumbers">{{ n }}</li>
    
    data: {
     number: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
     evenNumbers: function() {
         return this.number.fliter( function(number) {
             return number % 2 === 0
         })
     }
    }
    

    方法

    <li v-for="n in even(numbers)">{{ n }}</li>
    
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    methods: {
      even: function (numbers) {
        return numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
    

在 <template> 上使用 v-for

  1. 利用带有 v-for<template> 来循环渲染一段包含多个元素的内容
<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-for 与 v-if 一同使用

  1. v-for 的优先级比 v-if 更高
<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>

在组件上使用 v-for

  1. 当在组件上使用 v-for 时,key 现在是必须的
  2. 任何数据都不会被自动传递到组件里,组件有独立的作用域
<my-component v-for="item in items" :key="item.id"></my-component>
<div id="todo-list-example">
  <form v-on:submit.prevent="addNewTodo">
    <label for="new-todo">Add a todo</label>
    <input
      v-model="newTodoText"
      id="new-todo"
      placeholder="E.g. Feed the cat"
    >
    <button>Add</button>
  </form>
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="todo.id"
      v-bind:title="todo.title"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>
Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">Remove</button>\
    </li>\
  ',
  props: ['title']
})

new Vue({
  el: '#todo-list-example',
  data: {
    newTodoText: '',
    todos: [
      {
        id: 1,
        title: 'Do the dishes',
      },
      {
        id: 2,
        title: 'Take out the trash',
      },
      {
        id: 3,
        title: 'Mow the lawn'
      }
    ],
    nextTodoId: 4
  },
  methods: {
    addNewTodo: function () {
      this.todos.push({
        id: this.nextTodoId++,
        title: this.newTodoText
      })
      this.newTodoText = ''
    }
  }
})
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容

  • 主要还是自己看的,所有内容来自官方文档。 介绍 Vue.js 是什么 Vue (读音 /vjuː/,类似于 vie...
    Leonzai阅读 3,347评论 0 25
  • 1. Vue 实例 1.1 创建一个Vue实例 一个 Vue 应用由一个通过 new Vue 创建的根 Vue 实...
    王童孟阅读 1,019评论 0 2
  • 条件渲染 v-if 在<template>元素上使用v-if条件渲染分组 最终的渲染结果将不包含<template...
    oWSQo阅读 778评论 1 0
  • 1.用 v-for 把一个数组对应为一组元素 我们用 v-for 指令根据一组数组的选项列表进行渲染。v-for ...
    Sunshinga阅读 195评论 0 0
  • 一. Vue 实例 以后你可以在 API 参考中查阅到完整的实例属性和方法的列表。 实例生命周期钩子 比如 cre...
    兔子___阅读 339评论 0 0