小QA学习前端系列之vue 列表渲染

小QA学习前端系列之vue 列表渲染

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

我们用 v-for 指令根据一组数组的选项列表进行渲染。v-for 指令需要使用 item in items 形式的特殊语法,items 是源数据数组并且 item 是数组元素迭代的别名。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<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 使用index

v-for 还支持一个可选的第二个参数为当前项的索引。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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 迭代器的语法

一个对象的 v-for

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})

你也可以提供第二个的参数为键名:

1
2
3
<div v-for="(value, key) in object">
{{ key }}: {{ value }}
</div>

第三个参数为索引:

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

数组更新检测

变异方法

Vue 包含一组观察数组的变异方法,所以它们也将会触发视图更新。这些方法如下:

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

你打开控制台,然后用前面例子的 items 数组调用变异方法:example1.items.push({ message: ‘Baz’ }) 。

替换数组

变异方法 (mutation method),顾名思义,会改变被这些方法调用的原始数组。相比之下,也有非变异 (non-mutating method) 方法,例如:filter(), concat() 和 slice() 。这些不会改变原始数组,但总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:

example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})

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

对象更改检测注意事项

Vue 不能检测对象属性的添加或删除:
对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性。例如,对于:

1
2
3
4
5
6
7
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})

你可以添加一个新的 age 属性到嵌套的 userProfile 对象:

1
Vue.set(vm.userProfile, 'age', 27)

你还可以使用 vm.$set 实例方法,它只是全局 Vue.set 的别名:

1
this.$set(this.userProfile, 'age', 27)

有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()。在这种情况下,你应该用两个对象的属性创建一个新的对象。所以,如果你想添加新的响应式属性,不要像这样:

1
2
3
4
5
6
Object.assign(this.userProfile, {
age: 27,
favoriteColor: 'Vue Green'
})
``
你应该这样做:

this.userProfile = Object.assign({}, this.userProfile, {
age: 27,
favoriteColor: ‘Vue Green’
})

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

  • data: {
    numbers: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
    evenNumbers: function () {
    return this.numbers.filter(function (number) {
    return number % 2 === 0
    })
    }
    }

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

  • data: {
    numbers: [ 1, 2, 3, 4, 5 ]
    },
    methods: {
    even: function (numbers) {
    return numbers.filter(function (number) {
    return number % 2 === 0
    })
    }
    }

    1
    2
    3
    ## 一段取值范围的 v-for
    v-for 也可以取整数。在这种情况下,它将重复多次模板。




    1
    2
    ## v-for on a <template>
    类似于 v-if,你也可以利用带有 v-for<template> 渲染多个元素。比如:




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




  • 1
    2
    3
    上面的代码只传递了未 complete 的 todos。
    而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>)上。如:





    No todos left!


    1
    2
    ## 一个组件的 v-for
    在自定义组件里,你可以像任何普通元素一样用 v-for 。


    1
    2
    3
    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”


    1
    2
    3
    不自动将 item 注入到组件里的原因是,这会使得组件与 v-for 的运作紧密耦合。明确组件数据的来源能够使组件在其他场合重复使用。
    下面是一个简单的 todo list 的完整例子:




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



    1
    注意这里的 is="todo-item" 属性。这种做法在使用 DOM 模板时是十分必要的,因为在 <ul> 元素内只有 <li> 元素会被看作有效内容。这样做实现的效果与 <todo-item> 相同,但是可以避开一些潜在的浏览器解析错误。查看 DOM 模板解析说明 来了解更多信息。

    Vue.component(‘todo-item’, {
    template: ‘\

  • \
    小QA学习前端系列之vue 列表渲染\
    \
  • \
    ‘,
    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 = ‘’
    }
    }
    })
    ```