Designed by 77
加载资源 ......
感谢 ♥ 作者
先不感谢了

vue2.x学习笔记(八)

接着前面的内容:https://www.cnblogs.com/yanggb/p/12577433.html

列表渲染

vue提供了一个【v-for】指令用于列表渲染(循环)。

用【v-for】指令把一个数组对应为一组元素

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

<ul id="example-1">
  <li v-for="item in items">
    {{ item.message }}
  </li>
</ul>
var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

在【v-for】块中,我们可以访问所有父作用域的属性。此外,【v-for】指令还支持一个可选的第二参数,为当前项的索引。

<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',
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

当然了,你也可以使用【of】替代【in】作为分隔符,因为它更接近javascript迭代器的语法。

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

是不是像极了javascript中的【for-of】语法?

在【v-for】指令中使用对象

除了遍历数组之外,【v-for】指令还可以用于遍历一个对象的属性。

<ul id="v-for-object" class="demo">
  <li v-for="value in object">
    {{ value }}
  </li>
</ul>
new Vue({
  el: '#v-for-object',
  data: {
    object: {
      title: 'How to do lists in Vue',
      author: 'Jane Doe',
      publishedAt: '2016-04-10'
    }
  }
})

同样的,你也可以提供第二个参数作为property的名称(key键名)。

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

更多的,还可以使用第三个参数作为索引。

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

注意到遍历数组和遍历对象的差别了吗?这里有个差别就是遍历对象是支持三个参数的,分别是键值、键名和索引,而遍历数组则只支持两个参数,分别是元素和索引。

另外要注意的是,在遍历对象的时候,会按照Object.keys()的结果遍历,但是不能保证它的结果在不同的javascript引擎下都一致。

维护状态

当vue正在更新使用【v-for】指令渲染的元素列表的时候,默认采用的是【就地更新】的策略。意思就是说,如果数据项的顺序被改变,vue是不会移动dom元素来匹配数据项的顺序的,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染,类似于vue1.x的【track-by="$index"】。

这个默认模式是高效的,但是只适用于不依赖子组件状态或临时dom状态(例如表单输入值)的列表渲染输出。为了给vue一个提示,以便它能跟踪每个节点的身份,从而重用和排序现有元素,你需要为每个项提供一个唯一的key属性值。

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

建议尽可能在使用【v-for】指令的时候提供key属性,除非遍历输出的dom内容非常简单,或者是刻意依赖默认行为以获得性能上的提升。

因为key是vue识别节点的一个通用机制,并不是仅仅与【v-for】指令有特别关联。事实上,其还有一些别的用途,在之后的学习中会再次得到更多的了解。

此外,官方文档特别标注了,不要使用对象或数组之类的非基本类型值作为【v-for】指令的key,请用字符串或数值类型的值,否则可能导致意外的问题。

在【v-for】指令中的使用值范围

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

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

其实就是一个固定次数的循环。

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

因为<template>是vue模板的语法,所以并不会被渲染到最终的输出结果中。

【v-for】指令和【v-if】指令一同使用

当【v-if】指令与【v-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-if】和【v-for】指令放在同一个元素中,相当于在循环中写if,而将【v-if】提在【v-for】指令外层,则相当于在if中写循环。

在组件使用【v-for】指令

在自定义的组件上,可以像任何普通元素一样使用【v-for】指令。

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

在2.2.0+的版本,当在组件上使用【v-for】指令的时候,key是必须的,目的是使每个组件实例能独立被渲染。

在上面的例子中,并没有自动传递任何数据到组件中,这是因为组件拥有着自己的独立作用域。为了能够把迭代的数据传递到组件中,我们必须使用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>
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 = ''
    }
  }
})

注意这里的【is="todo-item"】属性,这样的写法和【<todo-item></todo-item>】的写法效果是一样的,但是可以避开一些潜在的浏览器解析错误。因为在<ul>元素里只有<li>元素会被看作有效内容,这样的写法就相当于给组件套模板,将组件里定义的<li>元素套到页面的<li>元素上。简单的理解就是规范组件的套用从而避免浏览器解析组件出错,因此这种写法在使用dom模板的时候是十分必要的。

 

"我还是很喜欢你,像仲夏流萤四起,弦月沉西。"

posted @ 2020-04-08 07:26  yanggb  阅读(319)  评论(0编辑  收藏  举报