迭代对象

当从 API 请求数据时,您通常会迭代包含逻辑和原始内容的对象数组。Vue 通过指令语法可以轻松控制数据的各种状态。条件指令控制 Vue 中 DOM 元素的显示状态。当涉及到组件中设置的显示规则时,HTML 语法提供了清晰的可见性。

练习 1.09:对对象数组使用 v-for 循环并将其属性用于 v-if 条件

在本练习中,我们将控制 Vue 数据数组并迭代其中的对象。

要访问本练习的代码文件,请参阅 https://packt.live/32YokKa

  1. 打开命令行终端,导航到 Exercise1.09 文件夹,然后按顺序运行以下命令:

    > cd Exercise1.09/
    > code .
    > yarn
    > yarn serve
  2. Exercise1-09.vue 中编写以下语法,并创建一个包含 title 字符串和 favorite 的字符串数组的数据对象。我们将像字符串数组一样循环遍历兴趣对象;但是,您需要引用 interests 对象中的 title 键:

    <template>
        <div>
            <h1>Looping through array of objects</h1>
            <ul>
                <li v-for="(item, n) in interests" :key="n">
                {{ item.title }}
                </li>
            </ul>
        </div>
    </template>

    上述代码的输出如下:

    image 2023 10 11 16 39 33 061
    Figure 1. Figure 1.28: You should see a list of titles now in the frontend
  3. 让我们创建第二个 v-for 循环来迭代您的收藏夹列表。请注意,我们对嵌套循环使用不同的键(favm)。这是因为您仍然可以在嵌套循环上下文中使用值 itemn

    Figure 1.29 displays an output where looping is performed through an array of objects
    <template>
        <div>
            <h1>Looping through array of objects</h1>
            <ul>
                <li v-for="(item, n) in interests" :key="n">
                    {{ item.title }}
                    <ol>
                        <li v-for="(fav, m) in item.favorite" :key="m">{{ fav }}</li>
                    </ol>
                </li>
            </ul>
        </div>
    </template>
    image 2023 10 11 16 44 46 329
    Figure 2. Figure 1.29: Nested ordered list detailing your favorites
  4. 为了优化 DOM 树,我们可以使用 Exercise 1.09 中的 v-if 条件指令来隐藏不必要的 DOM 元素:

    image 2023 10 11 16 46 13 328
    Figure 3. Figure 1.30: Displaying empty DOM elements in your virtual DOM
  5. 我们将检查数组中是否有超过 0 个项目来显示有序列表 HTML 元素。将 v-if 指令添加到 <ol> 中,条件为 item.favorite.length > 0

// src/components/Exercise1-09.vue
<template>
    <div>
        <h1>Looping through array of objects</h1>
        <ul>
            <li v-for="(item, n) in interests" :key="n">
                {{ item.title }}
                <ol v-if="item.favorite.length > 0">
                    <li v-for="(fav, m) in item.favorite" :key="m">{{ fav }}</li>
                </ol>
            </li>
        </ul>
    </div>
</template>

这不会对页面的视觉效果产生影响,但是当您在浏览器中检查虚拟 DOM 树时,您会注意到开发模式下的 HTML 注释,使您能够了解 v-if 语句在哪里可能是 false。 当您进行生产构建时,这些 HTML 注释不会出现在您的 DOM 中。

image 2023 10 11 16 54 03 130
Figure 4. Figure 1.31: Output displaying no HTML comment in production builds

通过在开发模式下使用 v-if 指令,您将看到 HTML 注释。这些不会存在于生产版本中。

在本练习中,我们能够迭代复杂的对象数组,输出这些对象的嵌套键并根据长度条件控制 DOM 元素的视图状态。

Vue中方法

Vue 方法在 Vue 实例内的 methods 对象内定义,可以像普通 JavaScript 函数一样编写,在其中定义要执行的一段逻辑。当您使用 JavaScript 函数时,通常,您要么返回一个值,要么简单地执行一个全局操作。 编写函数和 Vue 方法之间的主要区别在于,Vue 方法的作用域为 Vue 组件,并且可以从编写它的组件内的任何位置运行。 由于这些方法的范围仅限于组件的 Vue 实例,因此您可以在 HTML 模板中的事件指令内轻松引用它们。 在 Vue 中将事件绑定到 HTML 元素时,可以使用 @ 符号;例如,v-on:click 相当于 @click

练习 1.10:触发方法

在本练习中,我们将构建一个使用 Vue 方法 API 的组件。考虑一下这些 Vue 方法可以像您自己的 JavaScript 命名函数一样编写,因为它们的行为方式非常相似。 练习结束时,我们应该能够使用方法并从 HTML 模板触发它们。

要访问本练习的代码文件,请参阅 https://packt.live/3kMTWs5

  1. 打开命令行终端并导航到 Exercise1.10 文件夹并按顺序运行以下命令:

    > cd Exercise1.10/
    > code .
    > yarn
    > yarn serve
  2. 让我们循环一个方法触发器并将其编号传递给一个方法。在 HTML 列表上设置匿名 v-for 循环,并在列表元素内添加锚元素。将循环设置为迭代 5 次:

    <template>
        <div>
            <h1>Triggering Vue Methods</h1>
            <ul>
                <li v-for="n in 5" :key="n">
                    <a href="#">Trigger</a>
                </li>
            </ul>
        </div>
    </template>
  3. 添加引用名为 triggerAlert 的方法的 @click 指令,并将 n 的值作为参数传递。使用花括号将值 n 输出到锚元素文本中:

    <template>
        <div>
            <h1>Triggering Vue Methods</h1>
            <ul>
                <li v-for="n in 5" :key="n">
                    <a href="#" @click="triggerAlert(n)">Trigger {{ n }}</a>
                </li>
            </ul>
        </div>
    </template>
  4. methods 对象内,添加带有 n 参数的 triggerAlert(n) 键。在此方法中,添加一个 alert 函数,它将输出值 n 以及一些静态文本:

    <script>
    export default {
        methods: {
            triggerAlert(n) {
                alert(`${n} has been clicked`)
            },
        },
    }
    </script>
  5. 在组件底部的 <style> 标记内添加样式,并将 lang 属性设置为 scss

    <style lang="scss" scoped>
    ul {
      padding-left: 0;
    }
    li {
      display: block;
      list-style: none;
    
      + li {
        margin-top: 10px;
      }
    }
    
    a {
      display: inline-block;
      background: #4fc08d;
      border-radius: 10px;
      color: white;
      padding: 10px 20px;
      text-decoration: none;
    }
    </style>
  6. 您的页面应包含一个按钮列表,单击这些按钮时,会触发一条警报,并显示一条消息,其中包含您单击的按钮编号,如下所示:

    image 2023 10 11 17 12 01 051
    Figure 5. Figure 1.32: Output a list of triggers

    单击触发器时会出现以下提示:

    image 2023 10 11 17 12 48 769
    Figure 6. Figure 1.33: Displaying a browser alert with the index number in it

    虽然您可以将事件指令添加到任何 HTML 元素,但建议将它们应用于本机 HTML 交互元素,例如锚标记、表单输入或按钮,以帮助浏览器可访问性。

在本练习中,我们能够利用 Vue 方法 API 从 HTML 模板定义和触发方法,并将参数动态解析到每个方法中。

练习 1.11:使用 Vue 方法返回数据

在本练习中,我们将学习如何使用 Vue 方法作为函数来返回 Vue 实例和模板内部的数据。

通常在 Web 应用程序中,我们希望元素根据条件是否满足而显示在页面上。例如,如果我们的产品没有库存,我们的页面应该显示缺货的事实。

因此,让我们弄清楚如何根据我们的产品是否有库存来有条件地渲染这些元素。

要访问本练习的代码文件,请参阅 https://packt.live/3pHWCeh

  1. 打开命令行终端,导航到 Exercise1.11 文件夹,然后按顺序运行以下命令:

    > cd Exercise1.11/
    > code .
    > yarn
    > yarn serve
  2. 让我们迭代随机数量并触发 addToCart 方法。设置两个数据对象:totalItemstotalCost,当用户单击我们的商店按钮时,它们将被更新。接下来,通过指定 this 来引用 Vue 脚本块内的数据对象。例如,在模板块中,我们将 totalItems 称为 {{totalItems}},但在脚本块中,我们将其称为 this.totalItems。相同的模式用于 addToCart 在另一个方法中被称为 this.addToCart 的方法:

    <template>
        <div>
            <h1>Returning Methods</h1>
            <div>Cart({{ totalItems }}) {{ totalCost }} </div>
            <ul>
                <li v-for="n in 5" :key="n">
                    <a href="#" @click="addToCart(n)">Add {{ n }}</a>
                </li>
            </ul>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                totalItems: 0,
                totalCost: 0,
            }
        },
        methods: {
            addToCart(n) {
                this.totalItems = this.totalItems + 1
                this.totalCost = this.totalCost + n
            },
        },
    }
    </script>
    <style lang="scss" scoped>
    ul {
      padding-left: 0;
    }
    li {
      display: block;
      list-style: none;
    
      + li {
        margin-top: 10px;
      }
    }
    
    a {
      display: inline-block;
      background: rgb(235, 50, 50);
      border-radius: 10px;
      font-size: 10px;
      color: white;
      padding: 5px 10px;
      text-decoration: none;
    }
    </style>

    这将生成如下输出:

    image 2023 10 11 20 04 46 705
    Figure 7. Figure 1.34: Pressing any of the buttons will demonstrate the cart logic

    单击按钮时,商品计数器应增加 1,但成本将增加 n 值,这应演示正常的购物车功能(单击 “Add 2”,然后单击 “Add 5”):

    image 2023 10 11 20 05 48 774
    Figure 8. Figure 1.35: Output displaying Returning Methods after increments
  3. 我们来谈谈钱。我们可以使用方法来执行逻辑操作,根据事件来增强或格式化字符串。创建一个名为 formatCurrency 的方法,该方法接受一个参数。在赋予小数点后两位和一个 $ 符号后,我们将返回相同的值。要在模板中使用该方法,只需将其添加到内插的大括号中,然后在方法中将原来的值作为参数传递即可:

    <template>
        <div>
            <h1>Returning Methods</h1>
            <div>Cart({{ totalItems }}) {{ formatCurrency(totalCost) }}
            </div>
            <ul>
                <li v-for="n in 5" :key="n">
                    <a href="#" @click="addToCart(n)">Add {{ formatCurrency(n) }}</a>
                </li>
            </ul>
        </div>
    </template>
    
    <script>
    export default {
        data() {
            return {
                totalItems: 0,
                totalCost: 0,
            }
        },
        methods: {
            addToCart(n) {
                this.totalItems = this.totalItems + 1
                this.totalCost = this.totalCost + n
            },
            formatCurrency(val) {
                return `$${val.toFixed(2)}`
            },
        },
    }
    </script>

以下屏幕截图显示了上述代码的输出:

image 2023 10 11 20 09 54 382
Figure 9. Figure 1.36: Now all the values are expected to look like currency, while retaining the cart counter

在本练习中,我们能够利用 Vue 的方法 API 将参数解析为方法、返回修改后的值,并使用方法在逼真的场景中更新本地数据状态。