列表渲染

\color{red}{v-for}把一个数组对应为一组元素


v-for指令基于一个数组来渲染一个列表。v-for指令需要使用item in items形式的特殊语法,其中items是元数据数组,而item则是被迭代的数组元素的别名

列:

<block v-for="item in items" :key="item.message">
    <view>
        {{item.message}}
    </view>
</block>
//数据
data() {
    return {
        items:[
            {message:"A"},
            {message:"B"},
            {message:"C"},
            {message:"D"}
        ]
    }
},

v-for语句块中,可以访问所有福作用域的属性。v-for还支持一个可选的第二个参数,即当前项的索引。

<block v-for="(item,index) in items" :key="index">
    <view>
        {{parentTitle}} -- {{index}} -- {{item.message}}
    </view>
</block>

data() {
   return {
       parentTitle:"标题",
           items:[
            {message:"A"},
            {message:"B"},
            {message:"C"},
            {message:"D"}
        ]
    }
},

也可以用of替代in作为分隔符,因为它更接近js迭代器的语法:

<div v-for="item of items"></div>

 

v-for里使用对象


也可以用v-for来遍历一个对象的属性。

<block v-for="value in object">
    <view>
        {{value}}
    </view>
</block>

data() {
    return {
        object:{
            title:'平凡的世界',
            auther:'路遥',
            publishedAt:'2020-09-09'
        }
    }
},

也可以提供第二个参数作为属性名(键名):

<block v-for="(value,name) in object">
    <view>
        {{name}}:{{value}}
    </view>
</block>

还可以用第三个参数作为索引:

<div v-for="(value, name, index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>

\color{red}{注意:}在遍历对小时,会按Object.keys()的结果遍历,但是不能保证它的结果在不同的js引擎下都一致。

 

维护状态


当vue正在使用v-for渲染元素列表时,他默认使用的就是就地更新的策略。如果数据项的顺序改变,vue将不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保他们在每个索引位置正确渲染。

这个默认模式是高效的,但是只适用于不依赖子组件状态或临时DOM状态(例如;表单输入值)的列表渲染输出。

为了给vue一个提示,以便他能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为没项提供一个唯一key的属性:

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>

建议尽可能在使用v-for的时候提供key属性。

不要使用对象或数组之类的非基本类型值作为v-forkey。请使用字符串或者数值类型的值。
 

数组更新检测

\color{green}{\#}变更方法

vue将被侦听的数组的变更方法进行了包裹,所以他们也将会触发视图更新。这些包裹过得方法包括:

  • push() 向数组的末尾添加新的元素
  • pop() 删除数组中的最后一个元素
  • shift() 删除数组的第一个元素
  • unshift() 在数组的开头添加元素
  • splice() 在数组的第2位置添加一个元素
  • sort() 数组排序
  • reverse() 数组中的元素翻转
\color{green}{\#}替换数组

变更方法:顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,如:
filter()concat()slice()。它们不会变更原数组,而总是返回一个新数组,当使用非变更方法时,可以用新数组替换旧数组:

example1.items = example1.items.filter(function (item) {
  return item.message.match(/Foo/)
})
\color{green}{\#}注意事项

由于js的限制,vue不能检测数组和对象的变化。
 

显示过滤/排序后的结果


若想要显示一个数组经过过滤或排序后的版本,而不实际变更或充值原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。
例如:

<li v-for="n in evenNumbers">{{ n }}</li>

data: {
  numbers: [ 1, 2, 3, 4, 5 ]
},
computed: {
//定义一个计算属性
  evenNumbers: function () {
    return this.numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

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

<ul v-for="set in sets">
  <li v-for="n in even(set)">{{ n }}</li>
</ul>

data: {
  sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
},
methods: {
//定义一个方法
  even: function (numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

 

v-for里使用值范围


v-for也可以接受整数,在这种情况下,他会把模板重复对应次数。

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

结果:

1 2 3 4 5 6 7 8 9 10
 

<template>上使用v-for


类似于v-if,你也可以利用带有v-for<template>来循环渲染一段包含多个元素的内容。
比如:

<ul>
  <template v-for="item in items">
    <li>{{ item.msg }}</li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

 

v-forv-if一同使用


注意我们 推荐在同一元素上使用v-ifv-for

当他们处于同一节点,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如:

<li v-for="todo in todos" v-if="!todo.isComplete">
  {{ todo }}
</li>

上面代码将值渲染未完成的todo。
而如果你的目的是有条件的跳过循环的执行,那么可以将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

<my-component v-for="item in items" :key="item.id"></my-component>

然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用prop:

<my-component
  v-for="(item, index) in items"
  v-bind:item="item"
  v-bind:index="index"
  v-bind:key="item.id"
></my-component>

不自动将item注入到组件里的原因是,这会使得组件与v-for的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。

以下是一个简单的todo列表的完整的例子:

<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>

注意:这里的is="todo-item"属性。这种做法在使用DOM模板时是十分必要的,因为在<ul>元素内只有<li>元素会被看作有效内容。这样做的实现的效果与<todo-item>相同,但是可以避开一些潜在的浏览器解析错误。

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,651评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,468评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,931评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,218评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,234评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,198评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,084评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,926评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,341评论 1 311
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,563评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,731评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,430评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,036评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,676评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,829评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,743评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,629评论 2 354

推荐阅读更多精彩内容