列表渲染

列表渲染

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

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

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

结果:

  • Foo
  • bar

v-for 块中,我们可以访问所有父作用域的 property。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' }
    ]
  }
})

结果:

  • Parent-0-Foo
  • Parent-1-Bar

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

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

v-for 里使用对象

你也可以用 v-for 来遍历一个对象的 property。

<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: '2020-04-10'
    }
  }
})

结果:

  • How to do lists in Vue
  • Jane Doe
  • 2020-04-10

你也可以提供第二个的参数为 property 名称 (也就是键名):

<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>
  • title: How to do lists in Vue
  • author: Jane Doe
  • publishedAt: 2020-04-10

还可以用第三个参数作为索引:

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

为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute:

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

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

因为它是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。后面我们将在指南中看到,它还具有其它用途。

数组更新检测

变更方法

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:

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

替换数组

变更方法,顾名思义,会变更调用了这些方法的原始数组。相比之下,也有非变更方法,例如 filter()concat()slice()。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组:

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

显示过滤/排序后的结果

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

例如:

<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-forv-if 一同使用

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

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

案例--品牌列表

<!DOCTYPE html>
<html lang="zh-cn">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../css/bootstrap.css">
    <link rel="stylesheet" href="../css/bootstrap3/css/bootstrap.css">
    <script src="../js/vue.js"></script>
</head>


<body>
    <div id="app" class="mx-3">


        <!-- 添加一条数据 -->
        <div class="panel panel-primary">
            <div class="panel-heading">
                <h3 class="panel-title">添加品牌</h3>
            </div>
            <div class="panel-body form-inline">
                <label>
                    <!-- Id: -->
                    <input class="form-control mx-2" type="text" v-model="addId" placeholder="添加的ID">
                </label>

                <label>
                    <!-- name: -->
                    <input class="form-control mx-2" type="text" v-model="addName" placeholder="添加的Name">
                </label>
                <button class="btn btn-info mx-2" @click="add">添加</button>
                <label>
                    <!-- 搜索名称或关键字: -->
                    <input type="text" class="form-control mx-2" placeholder="搜索名称或关键字:" v-model:value="keyWords" />
                </label>

            </div>
        </div>


        <table class="table table-bordered table-hover">
            <thead>
                <th>Id</th>
                <th>Name</th>
                <th>Ctime</th>

                <th>Operation</th>
            </thead>
            <tbody>
                <tr v-for="items in search(keyWords)" :key="items.id">
                    <td v-for="item in items">{{item}}</td>
                    <td>
                        <!-- 根据编号删除一条数据 -->
                        <button class="btn btn-danger" @click="del(items.id)">删除</button>
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</body>
<script>
    var vm = new Vue({
        el: "#app",
        data: {
            addId: '',
            addName: '',
            keyWords: "",
            list: [{
                    id: 1,
                    name: '奔驰',
                    ctime: new Date()
                },
                {
                    id: 2,
                    name: '宝马',
                    ctime: new Date()
                },
                {
                    id: 3,
                    name: '捷豹',
                    ctime: new Date()
                },
                {
                    id: 4,
                    name: '路虎',
                    ctime: new Date()
                }
            ]
        },
        methods: {
            add() {
                this.list.push({
                    id: this.addId,
                    name: this.addName,
                    ctime: new Date()
                });
                this.addId = this.addName = null;
            },
            del(id) {
                //在数组的some方法中如果return true就会终止循环
                this.list.some((item, i) => {
                    if (item.id == id) {
                        //从第i个位置移除1个元素。
                        this.list.splice(i, 1);
                        return true;
                    }
                })
            },
            search(keyWords) { //根据关键字进行数据的搜索
                var newList = [];
                this.list.forEach(item => {
                    if (item.name.indexOf(keyWords) != -1)
                        newList.push(item);
                })
                return newList;
            }
        }
    });
</script>

</html>
posted @ 2020-05-15 23:04  Maple_XL  阅读(294)  评论(0编辑  收藏  举报