购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.2.3 v-for

使用v-for指令可以对数组、对象进行循环,来获取到其中的每一个值。

1. v-for遍历数组

使用v-for指令,必须使用特定语法alias in expression,其中items是源数据数组,而item则是被迭代的数组元素的别名,具体格式如下:

    <div v-for="item in items">
       {{item}}
    </div>

下面看一个示例,使用v-for指令循环渲染一个数组。

【例4.12】v-for指令遍历数组(源代码\ch04\4.12.html)。

    <div id="app">
        <ul>
            <li v-for="item in nameList">
              姓名:{{item.name}}--{{item.score}}分--{{item.ranking}}
            </li>
        </ul>
    </div>
    <!--引入vue文件-->
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        //创建一个应用程序实例
        const vm= Vue.createApp({
            //该函数返回数据对象
            data(){
              return{
                      nameList:[
                          {name:'章小明',score:'368',ranking:'第二名'},
                          {name:'华少峰',score:'398',ranking:'第一名'},
                          {name:'云栖',score:'319',ranking:'第三名'}
                      ]
                }
             }
            //在指定的DOM元素上装载应用程序实例的根组件
         }).mount('#app');
    </script>

在谷歌浏览器中运行程序,按F12键打开控制台,并切换到“Elements”选项,结果如图4-15所示。

图4-15 v-for指令遍历数组

提示: v-for指令的语法结构也可以使用of替代in作为分隔符,例如:

    <li v-for="item in nameList">

在v-for指令中,可以访问所有父作用域的属性。v-for还支持一个可选的第二个参数,即当前项的索引。例如,修改上面示例,添加index参数,代码如下:

    <ul>
       <li v-for="(item,index) in nameList">
            {{index}}---姓名:{{item.name}}--{{item.score}}分--{{item.ranking}}
       </li>
    </ul>

在谷歌浏览器中运行程序,结果如图4-16所示。

图4-16 v-for指令的第二个参数

2. v-for遍历对象

遍历对象的语法和遍历数组的语法是一样的:

    value in object

其中object是被迭代的对象,value是被迭代的对象属性的别名。

【例4.13】v-for指令遍历对象(源代码\ch04\4.13.html)。

    <div id="app">
        <ul>
            <li v-for="item in nameObj">
                {{item}}
            </li>
        </ul>
    </div>
    <!--引入vue文件-->
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        //创建一个应用程序实例
        const vm= Vue.createApp({
            //该函数返回数据对象
            data(){
              return{
                nameObj:{
                    name:"苹果",
                    city:"烟台",
                    price:"8.88元每公斤"
                 }
               }
             }
            //在指定的DOM元素上装载应用程序实例的根组件
         }).mount('#app');
    </script>

在谷歌浏览器中运行程序,结果如图4-17所示。

图4-17 v-for指令遍历对象

还可以添加第二个参数,用来获取键值;获取选项的索引,可以添加第三个参数。比如,修改上面示例,添加index参数和key参数,代码如下:

    <li v-for="(item,key,index) in nameObj">
       {{index}}--{{key}}--{{item}}
    </li>

在谷歌浏览器中运行程序,结果如图4-18所示。

图4-18 添加第二、三个参数

3. v-for遍历整数

也可以使用v-for指令遍历整数。

【例4.14】v-for指令遍历整数(源代码\ch04\4.14.html)。

    <div id="app">
       <span v-for="item in 16">
           {{item}}
       </span>
    </div>
    <!--引入vue文件-->
    <script src="https://unpkg.com/vue@next"></script>
    <script>
       //创建一个应用程序实例
       const vm= Vue.createApp({
        }).mount('#app');
    </script>

在谷歌浏览器中运行程序,结果如图4-19所示。

图4-19 v-for指令遍历整数

4. 在<template>上使用v-for

类似于v-if,也可以利用带有v-for的<template>来循环渲染一段包含多个元素的内容。

【例4.15】在<template>上使用v-for(源代码\ch04\4.15.html)。

    <div id="app">
        <ul>
            <template  v-for="(item,key,index) in nameObj">
                <li>{{index}}--{{key}}--{{item}}</li>
            </template>
        </ul>
    </div>
    <!--引入vue文件-->
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        //创建一个应用程序实例
        const vm= Vue.createApp({
            data(){
              return{
                nameObj:{
                    name:"葡萄",
                    city:"吐鲁番",
                    price:"2.88元每公斤"
                 }
               }
             }
         }).mount('#app');
    </script>

在谷歌浏览器中运行程序,按F12键打开控制台,并切换到“Elements”选项,并没有看到<template>元素,结果如图4-20所示。

图4-20 在<template>上使用v-for

提示: template元素一般常和v-for和v-if一起结合使用,这样会使得整个HTML结构没有那么多多余的元素,整个结构会更加清晰。

5. 数组更新检测

Vue将被监听的数组的变异方法进行了包裹,它们也会触发视图更新。被包裹过的方法包括push()、pop()、shift()、unshift()、splice()、sort()和reverse()。

【例4.16】数组更新检测(源代码\ch04\4.16.html)。

    <div id="app">
        <ul>
            <li v-for="(item,index) in nameList">
                {{index}}--{{item}}
            </li>
        </ul>
    </div>
    <!--引入vue文件-->
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        //创建一个应用程序实例
        const vm= Vue.createApp({
            data(){
              return{
                nameList:["樊建章","博士学位","工资28000元"]
               }
             }
         }).mount('#app');
    </script>

在谷歌浏览器中运行程序,结果如图4-21所示。按F12键打开控制台,并切换到“Console”选项,在选项中输入“vm.nameList.push("工作年限3年")”,按Enter键,数据将添加到nameList数组中,在页面中也显示出添加的内容,如图4-22所示。

图4-21 初始化效果

图4-22 修改数据对象中的数组属性

还有一些非变异方法,例如filter()、concat()和slice()。它们不会改变原始数组,而总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组。

继续在浏览器控制台输入“vm.nameList=vm.nameList.concat(["职位总经理","年龄34岁"])”,把变更后的数组再赋值给Vue实例的nameList,按Enter键,可发现页面发生了变化,如图4-23所示。

图4-23 使用新数组替换原始数组

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

在Vue.js 3.x版本中,可以利用索引直接设置一个数组项,例如修改上面示例:

    <script>
        //创建一个应用程序实例
        const vm= Vue.createApp({
            data(){
              return{
                nameList: ["樊建章","博士学位","工资28000元"]
               }
             }
         }).mount('#app');
        //通过索引向数组nameList添加“工作年限3年”
        vm.nameList[3]=" 工作年限3年";
    </script>

在谷歌浏览器中运行程序,结果如图4-24所示。

图4-24 通过索引向数组添加元素

从上面结果可以发现,要添加的内容已经添加到数组中了。另外,还可以采用以下方法:

    //使用数组原型的splice()方法
    vm.nameList.splice(0,0,"员工介绍");

修改上面示例:

    <script>
        //创建一个应用程序实例
        const vm= Vue.createApp({
            data(){
              return{
                nameList: ["樊建章","博士学位","工资28000元"]
               }
             }
         }).mount('#app');
    //使用数组原型的splice()方法
    vm.nameList.splice(0,0,"员工介绍");
    </script>

在谷歌浏览器中运行程序,可发现要添加的内容在页面上已经显示,结果如图4-25所示。

图4-25 使用数组原型的splice()方法

6. key属性

当Vue正在更新使用v-for渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue将不会移动DOM元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。

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

下面我们先来看一个不使用key属性的示例。

在下面的示例中,定义一个nameList数组对象,使用v-for指令渲染到页面,同时添加三个输入框和一个“添加”按钮,可以通过“添加”按钮向数组对象中添加内容。在实例中定义一个add方法,在方法中使用unshift()数组的开头添加元素。

【例4.17】不使用key属性(源代码\ch04\4.17.html)。

在谷歌浏览器中运行程序,选中列表中的第一个选项,如图4-26所示;然后在输入框中输入新的内容,单击“添加”按钮后,向数组开头添加一组新数据,页面中也相应地显示,如图4-27所示。

图4-26 选中列表中的第一个选项

图4-27 添加后效果

从上面结果可以发现,刚才选择的“洗衣机”变成了新添加的“电视机”。很显然这不是想要的结果。

产生这种效果的原因就是v-for指令的“就地更新”策略,只记住了数组勾选选项的索引0,当往数组添加内容的时候,虽然数组长度增加了,但是指令只记得刚开始选择的数组下标,于是就把新数组中下标为0的选项选择了。

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

修改上面示例,在v-for指令的后面添加key属性。代码如下:

    <p v-for="item in nameList" v-bind:key="item.name">

此时再重复上面的操作,可以发现已经实现了想要的结果,如图4-28所示。

图4-28 使用key属性的结果

7. 过滤与排序

在实际开发中,可能一个数组需要在很多地方使用,有的地方是过滤后的数据,而有些地方是重新排列的数组。这种情况下,可以使用计算属性或者方法来返回过滤或排序后的数组。

【例4.18】过滤与排序(源代码\ch04\4.18.html)。

在谷歌浏览器中运行程序,结果如图4-29所示。

图4-29 过滤与排序

8. v-for与v-if一同使用

v-for与v-if一同使用,当它们处于同一节点上时,v-for的优先级比v-if更高,这意味着v-if将分别重复运行于每个v-for循环中。当只想渲染部分列表选项时,可以使用这种组合方式。

例如下面示例,循环输出商品的出库情况。

【例4.19】v-for与v-if一同使用(源代码\ch04\4.19.html)。

    <div id="app">
            <h3>已经出库的商品</h3>
            <ul>
                <template v-for="goods in goodss">
                    <li v-if="goods.isOut">
                        {{goods.name}}
                    </li>
                </template>
            </ul>
            <h3>没有出库的商品</h3>
            <ul>
                <template v-for="goods in goodss">
                    <li v-if="!goods.isOut">
                       {{goods.name}}
                   </li>
               </template>
           </ul>
    </div>
    <!--引入vue文件-->
    <script src="https://unpkg.com/vue@next"></script>
    <script>
        //创建一个应用程序实例
        const vm= Vue.createApp({
            data() {
               return {
                    goodss: [
                      {name: '洗衣机', isOut: false},
                      {name: '冰箱', isOut: true},
                      {name: '空调', isOut: false},
                      {name: '电视机', isOut: true},
                      {name: '电风扇', isOut: true},
                      {name: '电脑', isOut: false}
                    ]
               }
              }
        }).mount('#app');
    </script>

在谷歌浏览器中运行程序,结果如图4-30所示。

图4-30 v-for与v-if一同使用 4Xi5OV2IPQggIGQEaj/BNT0qveJWN3qOheWjW6Ajfml2L2ndTOwDuGE/Qw15JX0R

点击中间区域
呼出菜单
上一章
目录
下一章
×