用 v-for 将数组对应为一组元素

在 v-for 块中,我们拥有对父作用域属性的完全访问权限。v-for 还支持一个可选的第二个参数为当前项的索引

    <ul id="example-2">
        <li v-for="(item, index) in items">
            {{ parentMessage }} - {{ index }} - {{ item.message }}
        </li>
    </ul>

    <script type="text/javascript">
        var example2 = new Vue({
            el: '#example-2',
            data: {
                parentMessage: 'Parent',
                items: [
                    { message: 'Foo' },
                    { message: 'Bar' }
                ]
            }
        })
    </script>

渲染为:

Parent - 0 - Foo
Parent - 1 - Bar

上述也可以利用如下的写法,可以用 of 替代 in 作为分隔符

    <ul id="example-3">
        <li v-for="(item, index) of items">
            {{ parentMessage }} - {{ index }} - {{ item.message }}
        </li>
    </ul>

一个对象的 v-for

你也可以用 v-for 通过一个对象的属性来迭代。

    <ul id="v-for-object" class="demo">
        <li v-for="(value, key, index) in object">
            {{ index }}. {{ key }}: {{ value }}
        </li>
    </ul>

    <script type="text/javascript">
        new Vue({
            el: '#v-for-object',
            data: {
                object: {
                    firstName: 'John',
                    lastName: 'Doe',
                    age: 30
                }
            }
        })
    </script>

浏览器渲染结果如下:

0. firstName: John
1. lastName: Doe
2. age: 30

key复用

为了给 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 还具有其他用途

数组利用索引设置项值

由于 JavaScript 的限制,Vue 不能检测以下变动的数组:

当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
举个例子

var vm = new Vue({
  data: {
    items: ['a', 'b', 'c']
  }
})
vm.items[1] = 'x' // 不是响应性的
vm.items.length = 2 // 不是响应性的

以下两种方式都可以实现和 vm.items[indexOfItem] = newValue 相同的效果,同时也将触发状态更新

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

// Array.prototype.splice
vm.items.splice(indexOfItem, 1, newValue)
    <div id="div1">
        <p v-for="item in items">{{item}}</p>

    </div>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#div1",
            data: {
                items: ['a', 'b', 'c']
            }
        })
        // 解决vm.items[1] = 'x' // 不是响应性的
        Vue.set(vm.items, 1, "d")
        vm.items.splice(0, 1, "dd");
        vm.$set(vm.items, 2, "cc");
        // 解决vm.items.length = 2 // 不是响应性的
        vm.items.splice(5)
    </script>

浏览器渲染输出

dd

d

cc

对象属性的添加或删除

还是由于 JavaScript 的限制,Vue 不能检测对象属性的添加或删除:

var vm = new Vue({
  data: {
    a: 1
  }
})
// `vm.a` 现在是响应式的

vm.b = 2
// `vm.b` 不是响应式的

我们来看下面的例子

<ul id="div2">
        <li v-for="(value, key) in userProfile">
            {{ key }}: {{ value }}
        </li>
    </ul>
    <script type="text/javascript">
        var vm = new Vue({
            el: "#div2",
            data: {
                userProfile: {
                    name: 'Anika'
                }
            }
        })
        Vue.set(vm.userProfile, 'age', 27);
        vm.$set(vm.userProfile, 'sex', "男");
        // 有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()
        vm.userProfile = Object.assign({}, vm.userProfile, {
            ager: 27,
            favoriteColor: 'Vue Green'
        })
    </script>

渲染输出如下:

name: Anika
age: 27
sex: 男
ager: 27
favoriteColor: Vue Green

显示过滤/排序结果

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

<ol id= "div3">
            <li  v-for="n in evenNumbers">{{ n }}</li>
        </ol>
    
        <script type="text/javascript">
            new Vue({
                el:"#div3",
                data: {
                    numbers: [ 1, 2,3,4,5]
                },
                computed: {
                    evenNumbers: function () {
                        return this.numbers.filter(function (number) {
                            console.log(number)
                            return number % 2 === 0
                        })
                    }
                }
            })
        </script>

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

<ol id= "div4">
            <li v-for="n in even(numbers)">{{ n }}</li>
        </ol>
        
        <script type="text/javascript">
            new Vue({
                el:"#div4",
                data: {
                    numbers: [ 1, 2, 3, 4, 5 ]
                },
                methods: {
                    even: function (numbers) {
                        return this.numbers.filter(function (number) {
                            return number % 2 === 0
                        })
                    }
                }
            })
        </script>

v-for on a template

类似于 v-if,你也可以利用带有 v-for 的 渲染多个元素。比如:

   <ul id="ul">
                <template v-for="item in items">
                    <li>{{ item.msg }}</li>
                    <li class="divider"></li>
                </template>
            </ul>
            <script type="text/javascript">
                new Vue({
                    el:"#ul",
                    data:{
                        items:[{msg:"a"},{msg:"b"}]
                    }
                })
            </script>

渲染输出如下:

a
b

v-for with v-if

 <div id="forAndIf">
        <ul>
            <li v-for="todo in todos" v-if="todo!=='isb'">
                <!-- v-if='todo!=='isb' 用来判断 todos中的属性值是否为字符串isb,若不是则显示。
            此外v-if的属性值若设置为以下的数据对应显示的结果:
            0,false,null ,undefined 显示为空白
            1,2,‘’,true   显示为全部属性值
            说到底,v-if是一个判断语句,若为真则显示,为假不显示。-->
                {{todo}}
            </li>
        </ul>
    </div>
    <script>
        var forif = new Vue({
            el: '#forAndIf',
            data: {
                todos: {
                    ist: 'ff',
                    isb: 'isb',
                    iss: 'iss'
                }
            }
        })
    </script>

渲染输出如下:

ff
iss

组件v-for

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

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


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

效果图:
在这里插入图片描述

Logo

前往低代码交流专区

更多推荐