8-Vue指令之列表渲染 V-for

1. v-for循环渲染标签
+ v-for 指令根据一组数组的选项列表进行渲染。
+ v-for 指令需要以“ item in items ”形式的特殊语法, items 是源数据数组并且 item 是数组元素迭代的别名。
+ 模板引擎都会提供循环的支持,基本的用法类似于foreach的用法。

 <div id="app">
        <table>
            <thead>
                <tr>
                    <th>姓名</th>
                    <th>年龄</th>
                    <th>地址</th>
                </tr>
            </thead>

       <tbody>
<!--每次 for 循环都会创建一个 tr 标签 item 是遍历元素-->
                   <tr v-for = 'item in UserList'>
                        <td> {{ item.name }} </td>
                        <td> {{ item.age }} </td>
                        <td> {{ item.gender }}</td>
                  </tr>  
            </tbody>
        </table>

    var vm = new Vue({
       el: '#app',
       data: {
          UserList: [
              {'name':'meimei','age':18,'gender':'女'},
              {'name':'lilei','age':18,'gender':'男'},
              {'name':'sundy','age':18,'gender':'女'},
                    ]
                }
            })
  • 在 v-for 块中,我们拥有对父作用域属性的完全访问权限
  • v-for 还支持一个可选的第二个参数为当前项的索引
    <ul id="example">
        <li v-for = '(item,index) in items'>
        {{parentMessage}}--{{index}}--{{ item.message}}
        </li>  
    </ul>

      var example1 = new Vue({
            el: '#example',
            data: {
                parentMessage: 'parent',
                items: [
                    {message : 'foo'},
                    {message : 'var'},
                    {message : 'bnb'},
                ],   
            }
        })

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

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

2.Template 循环渲染多标签
上面的例子,我们演示的是 每次循环输出一个 tr 标签。如果我们希望每次循环生成多个标签呢?
Vue给我们提供了 <template> 标签来渲染多个元素块,供我们用于 v-for 循环中进行处理。

<ul>
  <!-- 通过template标签,可以一次循环,输出两个li标签 -->
  <template v-for="item in items">
     <li>{{ item.msg }}</li>
     <li class="divider"></li>
  </template>
</ul>

3. 对象循环渲染

  <ul id = 'example'>
        <li v-for = 'value in object'>{{ value }}</li>
 </ul> 


        var example1 = new Vue({
            el: '#example',
            object: {
                     firstName: 'John',
                     lastName: 'Doe',
                     age: 30
                }
        })

也可以提供第二个的参数为键名,第三个参数为索引

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

在遍历对象时,是按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。

4. 整数循环渲染
v-for 也可以取整数。在这种情况下,它将重复多次模板。

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

5. 组件 和 v-for
在自定义组件里,你可以像任何普通元素一样用 v-for 。

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

2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的。

然而他不能自动传递数据到组件里,因为组件有自己独立的作用域。为了传递迭代数据到组件里,我们要用 props :

<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 list 完整的例子:

<div id="example">
  <input
      v-model="Text"
      v-on:keyup.enter="addNewTodo"
      placeholder="Add a todo"  >
  <ul>
    <li
      is="todo-item"
      v-for="(todo, index) in todos"
      v-bind:key="index"
      v-bind:title="todo"
      v-on:remove="todos.splice(index, 1)"
    ></li>
  </ul>
</div>

Vue.component('todo-item', {
  template: '\
    <li>\
      {{ title }}\
      <button v-on:click="$emit(\'remove\')">X</button>\
    </li>\
  ',
  props: ['title']
})

new Vue({
  el: '#example',
  data: {
     Text: '',
     todos: [
       'Do the dishes',
       'Take out the trash',
       'Mow the lawn'
     ]
  },
  methods: {
      addNewTodo: function () {
        this.todos.push(this.Text)
        this.Text = ''
    }
  }
})

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

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

上面的代码只传递了未 complete 的 todos。
而如果你的目的是有条件地跳过循环的执行,那么将 v-if 置于包装元素 (或 )上。如:

<ul v-if="shouldRenderTodos">
   <li v-for="todo in todos">
     {{ todo }}
   </li>
</ul>

7. key
+ 当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。
+ 如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。这个类似 Vue 1.x 的 track-by=”$index” 。

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

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有唯一 id。这个特殊的属性相当于 Vue 1.x 的 track-by ,但它的工作方式类似于一个属性,所以你需要用 v-bind 来绑定动态值(在这里使用简写):

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

建议尽可能使用 v-for 来提供 key ,除非迭代 DOM 内容足够简单,或者你是故意要依赖于默认行为来获得性能提升。
因为它是 Vue 识别节点的一个通用机制, key 并不特别与 v-for 关联,key 还具有其他用途,我们将在后面的指南中看到其他用途。

8. 数组更新检测
+ 8.1 变异方法
Vue 包含一组观察数组的变异方法,Vue 的机制就是检测数据的变化,自动更新 HTML 。
数组的变化,Vue 只检测部分函数,检测的函数执行时才会触发视图更新。、
+ push()
+ pop()
+ shift()
+ unshift()
+ splice()
+ sort()
+ reverse()
你打开控制台,然后用前面例子的 items 数组调用变异方法:example1.items.push({ message: ‘Baz’ }) 。

  • 8.2 重塑数组
    变异方法(mutation method),顾名思义,会改变被这些方法调用的原始数组。
    相比之下,也有非变异(non-mutating method)方法,例如: filter(), concat(), slice() 。这些不会改变原始数组,但总是返回一个新数组。
    当使用非变异方法时,可以用新数组替换旧数组:
example1.items = example1.items.filter(function (item) {
   return item.message.match(/Foo/)
})

你可能认为这将导致 Vue 丢弃现有 DOM 并重新渲染整个列表。幸运的是,事实并非如此。 Vue 实现了一些智能启发式方法来最大化 DOM 元素重用,所以用一个含有相同元素的数组去替换原来的数组是非常高效的操作。

  • 8.3 注意事项
    由于 JavaScript 的限制, Vue 不能检测以下变动的数组:
    1.当你利用索引直接设置一个项时,例如:
    vm.items[indexOfItem] = newValue
    2.当你修改数组的长度时,例如:

为了解决第一类问题,以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果, 同时也将触发状态更新:

// Vue.set
Vue.set(example1.items, indexOfItem, newValue)

// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)

为了解决第二类问题,你可以使用 splice:

example1.items.splice(newLength)

8.4. 显示过滤/排序结果
有时,我们想要显示一个数组的过滤或排序副本,而不实际改变或重置原始数据。
在这种情况下,可以创建返回过滤或排序数组的计算属性。

<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 循环中) 你可以使用一个 method 方法:

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

vue 中让 v-for 循环出来的列表里面的 click 事件只对当前列表内元素有效

<body>

    <div >
       <ul id="example">
           <li v-for = 'item in items' @click = 'toggle(item)'>
               <span v-show = 'item.show'> {{ item.content}} </span>
           </li>
       </ul>
    </div>


    <script>
        var vm = new Vue({
            el : '#example',
            data : function() {
                return {
                    items:[
                        {content: '1 item',show: true },
                        {content: '2 item',show: true },
                        {content: '3 item',show: true },
                    ]
                }
            },
            methods : {
                toggle : function (item) {
                    item.show = !item.show;
                }
            }
        })
    </script>
</body>
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值