Vue.js 的组件化架构让构建用户界面变得高效便捷。它允许你将应用分解成更小、可复用的组件,然后用这些组件构建更复杂的结构。
本指南将为您提供 Vue 组件的高级入门介绍。我们将探讨如何创建组件,如何在组件之间传递数据(通过 props 和事件总线),以及如何使用 Vue 的 <slot></slot>
元素在组件内渲染附加内容。每个示例都将附带可运行的 CodePen 演示。
关键要点
Vue.component
全局创建,也可以在单文件组件中局部创建,对于复杂的项目来说,后者由于封装了模板、脚本和样式,更适合使用。<slot></slot>
元素有助于在组件内嵌套内容,使其更灵活,并能够接收来自父组件的内容,这些内容可以用回退内容覆盖。如何在 Vue 中创建组件
组件本质上是具有名称的可重用 Vue 实例。在 Vue 应用中创建组件的方法有很多种。例如,在小型到中型项目中,您可以使用 Vue.component
方法注册全局组件,如下所示:
Vue.component('my-counter', { data() { return { count: 0 } }, template: `<div>{{ count }}</div>` }) new Vue({ el: '#app' })</pre>登录后复制
组件的名称是 my-counter
。它可以这样使用:
<div> <my-counter></my-counter> </div></pre>登录后复制
命名组件时,您可以选择使用 kebab-case(my-custom-component
)或 Pascal-case(MyCustomComponent
)。在模板中引用组件时,可以使用任何一种变体,但在直接在 DOM 中引用组件时(如上例所示),只有 kebab-case 标签名称有效。
您可能还会注意到,在上例中,data
是一个返回对象字面量的函数(而不是对象字面量本身)。这样做的目的是为了让组件的每个实例都拥有自己的数据对象,而不必与所有其他实例共享一个全局实例。
定义组件模板的方法有几种。上面我们使用了模板字面量,但我们也可以使用带有 text/x-template
的标记或 DOM 内模板。您可以在这里阅读有关定义模板的不同方法的更多信息。
单文件组件
在更复杂的项目中,全局组件很快就会变得难以管理。在这种情况下,将应用程序设计为使用单文件组件是有意义的。顾名思义,这些是具有 .vue
扩展名的单个文件,其中包含 <template>
、</pre>
而 MyCounter 组件可能如下所示:
Vue.component('my-counter', { data() { return { count: 0 } }, template: `<div>{{ count }}</div>` }) new Vue({ el: '#app' })</pre>登录后复制
如您所见,使用单文件组件时,可以直接在需要它们的组件中导入和使用它们。
Vue.component()
在本指南中,我将使用
使用单文件组件通常涉及构建步骤(例如,使用 Vue CLI)。如果您想了解更多信息,请查看本 Vue 系列中的“Vue CLI 入门指南”。
通过 Props 向组件传递数据
Props 使我们能够将数据从父组件传递到子组件。这使得我们的组件可以分成更小的块来处理特定的功能。例如,如果我们有一个博客组件,我们可能想要显示诸如作者详细信息、帖子详细信息(标题、正文和图像)和评论等信息。
我们可以将这些分解成子组件,以便每个组件处理特定的数据,使组件树看起来像这样:
<div> <my-counter></my-counter> </div></pre>登录后复制
如果您仍然不相信使用组件的好处,请花点时间意识到这种组合方式有多么有用。如果您将来要重新访问此代码,您会立即清楚页面是如何构建的,以及您应该在哪里(即在哪个组件中)查找哪个功能。这种声明式的方式来组合界面也使得不熟悉代码库的人更容易快速上手并提高效率。
由于所有数据都将从父组件传递,它可能如下所示:
<template> <div>{{ count }}</div> </template> <🎜></pre>登录后复制
author-detail
在上例组件中,我们定义了作者详细信息和帖子信息。接下来,我们必须创建子组件。让我们将子组件命名为
<blogpost> <authordetails></authordetails> <postdetails></postdetails> <comments></comments> </blogpost></pre>登录后复制
owner
我们将作者对象作为名为 owner
的 props 传递给子组件。这里需要注意区别。在子组件中,author
是我们从父组件接收数据的 props 名称。我们想要接收的数据称为
author-detail
要访问此数据,我们需要在
new Vue({ el: '#app', data() { return { author: { name: 'John Doe', email: 'jdoe@example.com' } } } })</pre>登录后复制
我们还可以在传递 props 时启用验证,以确保传递正确的数据。这类似于 React 中的 PropTypes。要在上面的示例中启用验证,请将我们的组件更改为如下所示:
<div> <author-detail :owner="author"></author-detail> </div></pre>登录后复制
如果我们传递错误的 prop 类型,您将在控制台中看到类似于我下面显示的错误:
Vue.component('author-detail', { template: ` <div> <h2>{{ owner.name }}</h2> <p>{{ owner.email }}</p> </div> `, props: ['owner'] })</pre>登录后复制
Vue 文档中有一份官方指南,您可以使用它来了解 prop 验证。
通过事件总线从子组件到父组件的通信
<script></code> 和 <code><style></code> 部分。</p> <p>对于上面的示例,App 组件可能如下所示:</p> <pre class="brush:php;toolbar:false"><code class="language-vue"><template> <div> <my-counter></my-counter> </div> </template> <script> import myCounter from './components/myCounter.vue' export default { name: 'app', components: { myCounter } } </script>事件通过创建包装方法来处理,这些方法在发生所选事件时触发。为了复习一下,让我们基于我们最初的计数器示例进行扩展,以便每次单击按钮时它都会增加。
我们的组件应该如下所示:
Vue.component('my-counter', { data() { return { count: 0 } }, template: `<div>{{ count }}</div>` }) new Vue({ el: '#app' })</pre>登录后复制
以及我们的模板:
<div> <my-counter></my-counter> </div></pre>登录后复制
这希望足够简单。如您所见,我们正在连接到 onClick
事件,以便在每次单击按钮时触发自定义的 increase
方法。然后,increase
方法会递增我们的 count
数据属性。现在让我们扩展示例,将计数器按钮移到单独的组件中,并在父组件中显示计数。我们可以使用事件总线来做到这一点。
当您想从子组件到父组件进行通信时,事件总线非常方便。这与默认的通信方法相反,默认的通信方法是从父组件到子组件。如果您的应用程序不够大,不需要使用 Vuex,则可以使用事件总线。(您可以在本 Vue 系列中的“Vuex 入门指南”中阅读更多相关信息。)
所以我们要做的是:计数将在父组件中声明并向下传递到子组件。然后在子组件中,我们要递增 count
的值,并确保父组件中的值得到更新。
App 组件将如下所示:
<template> <div>{{ count }}</div> </template> <🎜></pre>登录后复制
然后在子组件中,我们要通过 props 接收计数,并有一个方法来递增它。我们不想在子组件中显示 count
的值。我们只想从子组件进行递增,并使其反映在父组件中:
<blogpost> <authordetails></authordetails> <postdetails></postdetails> <comments></comments> </blogpost></pre>登录后复制
然后我们的模板将如下所示:
new Vue({ el: '#app', data() { return { author: { name: 'John Doe', email: 'jdoe@example.com' } } } })</pre>登录后复制
如果您尝试像那样递增值,它将不起作用。为了使其工作,我们必须从子组件发出一个事件,发送 count
的新值,并且还在父组件中监听此事件。
首先,我们创建一个新的 Vue 实例并将其设置为 eventBus
:
<div> <author-detail :owner="author"></author-detail> </div></pre>登录后复制
我们现在可以在我们的组件中使用事件总线。子组件将如下所示:
Vue.component('author-detail', { template: ` <div> <h2>{{ owner.name }}</h2> <p>{{ owner.email }}</p> </div> `, props: ['owner'] })</pre>登录后复制
每次调用 increment
方法时都会发出事件。我们必须在主组件中监听该事件,然后将 count
设置为我们通过发出的事件获得的值:
Vue.component('author-detail', { template: ` <div> <h2>{{ owner.name }}</h2> <p>{{ owner.email }}</p> </div> `, props: { owner: { type: Object, required: true } } })</pre>登录后复制
请注意,我们正在使用 Vue 的 created
生命周期方法在组件挂载之前连接到它,并设置事件总线。
如果您的应用程序不复杂,使用事件总线很好,但请记住,随着应用程序的增长,您可能需要改用 Vuex。
使用 Slots 嵌套组件中的内容
在我们到目前为止看到的示例中,组件都是自闭合元素。但是,为了创建可以以有用的方式组合在一起的组件,我们需要能够像使用 HTML 元素一样将它们彼此嵌套。
如果您尝试使用带有结束标签的组件并将一些内容放在里面,您会看到 Vue 只是将其吞噬了。组件的开始和结束标签之间的任何内容都将被组件本身的渲染输出替换:
Vue.component('my-counter', { data() { return { count: 0 } }, template: `<div>{{ count }}</div>` }) new Vue({ el: '#app' })</pre>登录后复制
幸运的是,Vue 的 slots 使得将任意值传递给组件成为可能。这可以是来自父组件到子组件的任何东西,从 DOM 元素到其他数据。让我们看看它们是如何工作的。
组件的脚本部分将如下所示:
<div> <my-counter></my-counter> </div></pre>登录后复制
然后模板将如下所示:
<template> <div>{{ count }}</div> </template> <🎜></pre>登录后复制
<list>
组件中的内容将在 <slot>
元素标签之间呈现。我们还可以使用回退内容,以防父组件没有注入任何内容。
<blogpost> <authordetails></authordetails> <postdetails></postdetails> <comments></comments> </blogpost></pre>登录后复制
如果没有来自父组件的内容,回退内容将呈现。
结论
这是一个关于在 Vue 中使用组件的高级介绍。我们研究了如何在 Vue 中创建组件,如何通过 props 从父组件到子组件进行通信,以及如何通过事件总线从子组件到父组件进行通信。然后,我们通过查看 slots 来结束,这是一种以有用的方式组合组件的便捷方法。我希望您觉得本教程有用。
(FAQs 部分略去,因为篇幅过长,且与伪原创目标不符。 FAQs 部分内容可以根据需要重新编写,但需保持原意不变。)
以上是与VUE组件合作的初学者指南的详细内容。更多信息请关注PHP中文网其他相关文章!