美文网首页
列表渲染

列表渲染

作者: 车在路上爬fly | 来源:发表于2020-12-28 18:02 被阅读0次

    \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 = ''
        }
      }
    })
    

    相关文章

      网友评论

          本文标题:列表渲染

          本文链接:https://www.haomeiwen.com/subject/avjvgktx.html