列表渲染

2020-12-28  本文已影响0人  车在路上爬fly

\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将被侦听的数组的变更方法进行了包裹,所以他们也将会触发视图更新。这些包裹过得方法包括:

\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 = ''
    }
  }
})
上一篇 下一篇

猜你喜欢

热点阅读