Mixins

Mixin 可以向使用它们的组件添加方法、属性和默认生命周期方法。在下面的示例中,我们定义了一个 mixin,它将一个 greet 方法和一个 greeting 字段添加到组件的 data 函数中:

export default {
    methods: {
        greet(name) {
            return `${this.greeting} ${name}`
        }
    },
    data() {
        return {
            greeting: 'Hello'
        }
    }
}

Mixins 允许独立定义多个组件的共享功能。它们通过 mixins 组件属性来使用,该属性接受一个数组。

在 App.vue 文件中,我们可以通过设置组件的 mixins 属性来使用 mixin。

然后,mixin 的属性和方法在组件中可用(就像在组件本身中定义它们一样):

<template>
    <div>{{ greet('World') }}</div>
</template>

<script>
import greeter from './mixins/greeter.js'
export default {
    mixins: [greeter]
}
</script>

这会在浏览器中显示以下消息:

image 2023 10 13 17 27 45 799
Figure 1. Figure 5.1: Hello World using a greeter mixin

当组件和 mixin 之间存在命名相同的实例属性或方法冲突时,组件获胜。这可以被认为是默认情况下采用 mixin 行为的组件,除非该组件声明相同的实例属性或方法。在这种情况下,mixin 中定义的实例访问将访问组件的实例。

例如,让我们向 App 组件添加一个 data() 初始值设定项,并将 greeting 设置为 Hi:

<script>
// other imports
export default {
    // other component properties
    data() {
        return {
            greeting: 'Hi'
        }
    }
}
</script>

mixin 定义了一个 data 方法,组件也定义了一个 data 方法。在这种情况下,组件获胜,因此显示的问候语是 Hi(如组件中定义)而不是 Hello(如 mixin 中定义),如以下屏幕截图所示:

image 2023 10 13 17 30 26 218
Figure 2. Figure 5.2: Hi World using a greeter mixin with overridden data

请注意,当组件未定义 data 方法时,将使用 mixin 的实现,但如果 mixin 和组件都定义了它,则组件 “获胜”。

Vue.js 生命周期钩子是提取到 mixin 中的主要候选者。我们可以使用的生命周期钩子(按执行顺序)是 beforeCreated、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy 和 destroyed。

生命周期钩子是前面提到的混合/组件冲突解决规则的一个例外。对于 Vue.js 生命周期钩子函数来说,对于每个 mixin、组件和钩子,钩子函数都按照 mixin 先(按添加到组件的顺序)、组件最后的顺序执行。

我们可以在下面的示例中看到这一点。让我们创建两个 mixins 来实现已安装的生命周期钩子并在组件中实现该钩子。这说明了用于 mixin/组件冲突解决的生命周期钩子的情况:

<template>
    <div ref="zone" />
</template>

<script>
const firstMixin = {
    mounted() {
        console.log('First mixin mounted hook')
    }
}
const secondMixin = {
    mounted() {
        console.log('Second mixin mounted hook')
    }
}
export default {
    mixins: [firstMixin, secondMixin],
    mounted() {
        console.log('Component mounted hook')
    }
}
</script>

该组件的浏览器控制台输出将(按顺序)第一个 mixin 安装钩子、第二个 mixin 安装钩子和组件安装钩子,如以下屏幕截图所示:

image 2023 10 13 17 34 15 869
Figure 3. Figure 5.3: Browser console output showing the hooks defined in the mixins that were executed before the component hooks

我们看到的所有示例都直接使用 mixin 将功能注入到组件中。Mixin 也可以通过使用 Vue.mixin 函数调用来全局创建。

例如,我们可以将 greeting 函数设为全局实例方法:

Vue.mixin({
    methods: {
        $greet(greeting, name) {
            return `${greeting} ${name}`
        }
    }
})

this.$greet 现在可在 Vue.mixin 调用后声明的所有 Vue 实例上使用。然而,这个用例最好通过插件来满足。

$methodName 约定在 Vue.js 中用于 Vue.js 应用程序实例(而不是当前组件实例)提供的方法。

练习 5.01:创建你自己的 Mixin

在本练习中,我们将创建一个名为 debug 的 mixin,它将返回已传递的输入的 JSON-stringified 表示形式。JavaScript 对象表示法或 JSON 是 JavaScript 的一个子集,它允许将对象和数组的注释以紧凑的人类和机器可读的格式放置。这对于将数据打印到控制台甚至页面上非常有用。 我们将使调试执行所谓的漂亮打印,以便我们可以更轻松地阅读它。

这对于调试 Vue 时在 HTML 中打印数据也很有用。 在 Vue.js DevTools 不可用或不可靠的情况下运行 Node.js 应用程序。 要访问本练习的代码文件,请参阅 https://packt.live/38ivgFq

我们将从一个干净的 Vue CLI 项目开始(可以使用 vue new exercise5.01 命令创建)。 Vue CLI 项目中的应用程序可以通过 npm run serve 启动。

请按照以下步骤完成本练习:

  1. 创建一个新的 src/mixins 文件夹和 src/mixins/debug.js 文件,我们将在其中定义 mixin 的框架:

    export default {}
  2. mixin 将添加一个 debug 方法,我们应该在 methods 下定义该方法。debug 方法将接收 obj 参数并返回 JSON.stringify 的输出。我们将使用 JSON.stringify(obj, null, 2) 输出两空格的漂亮打印 JSON:

    export default {
        methods: {
            debug(obj) {
                return JSON.stringify(obj, null, 2)
            }
        }
    }
  3. 我们现在可以从 src/App.vue 导入 debug mixin 并将其注册到 mixins 属性下:

    <script>
    import debug from './mixins/debug.js'
    export default {
        mixins: [debug],
    }
    </script>
  4. 要查看 debug 方法的实际效果,我们将在 src/App.vue 文件中添加一个 data 方法和一个 created 的钩子(我们可以从中打印 debug 的输出):

    <script>
    // imports
    export default {
        // other component properties
        data() {
            return {
                myObj: {
                    some: 'data',
                    other: 'values'
                }
            }
        },
        created() {
            console.log(this.debug(this.myObj))
        }
    }
    </script>

    您应该得到以下输出:

    image 2023 10 13 19 11 37 255
    Figure 4. Figure 5.4: Browser console output due to the created hook
  5. 模板中也可以进行 debug;我们可以将其输出插入到 pre 标记中,以便尊重空格:

<template>
    <div id="app">
        <pre>{{ debug(myObj) }}</pre>
    </div>
</template>

该应用程序以及该模板将如下所示:

image 2023 10 13 19 13 18 934
Figure 5. Figure 5.5: Browser printing myObj using the debug method from the mixin

至此,我们已经了解了如何使用 mixins 以非常明确的方式(mixins 属性)将共享功能注入到多个组件中。 我们还有机会看到当组件的实现覆盖 mixin 提供的属性和方法时会发生什么(通常是组件获胜)。

我们现在将了解如何 注入实例全局功能 并通过插件分发它。