函数式组件
函数式组件是常规 Vue.js 组件的子集。它们没有状态或组件实例。它们可以被认为是传递 props 的渲染(render)函数(如本章前面所示)。
我们可以将组件标记为函数式的(functional),这意味着它们是无状态的(没有反应数据)和无实例的(没有 |
有关更多信息,请参阅 Vue.js 文档 ( https://vuejs.org/v2/guide/render-function.html#Functional-Components )。
函数式组件只能访问从其父组件传递的 props、children、slots 和作用域 slot。他们还会收到 parents 和 listeners 的引用。
以下是一个 Greet 组件(在 Greet.vue 文件中)。注意模板(template)中的 functional:
<template functional>
<div>Functional Component: {{ props.greeting }} {{
props.audience }}</div>
</template>
函数式组件必须通过 props.propName 访问 props。函数式组件也可以用 function: true
布尔值表示,并与渲染(render)函数一起使用:
export default {
functional: true,
render(h, context) {
return h(
'h2',
`Functional Render: ${context.props.greeting}${context.props.audience}`
)
}
}
我们可以在 App.vue 文件中使用这两个函数式组件:
<template>
<div id="app">
<Greet greeting="Hello" audience="World" />
<GreetRender greeting="Hello" audience="World" />
</div>
</template>
<script>
import Greet from './components/Greet.vue'
import GreetRender from './components/GreetRender.js'
export default {
components: {
Greet,
GreetRender
}
}
</script>
这将向浏览器渲染以下内容:

函数式组件是封装仅渲染功能的好方法。也就是说,他们从 props 中派生出模板。它们的性能比常规组件稍好,因为它们没有任何关联的反应状态或组件实例。
我们针对非函数式组件介绍的一个常见用例是发出事件,可以按如下方式完成:
<template>
<input
type="submit"
@click="$emit('click', $event)"
/>
</template>
要使用函数式组件发出事件,我们可以将元素绑定到 listeners 对象中的属性。
要将所有事件委托给子级,我们可以使用 v-on="listeners":
<template functional>
<input
v-on="listeners"
v-bind="data.attrs"
/>
</template>
要绑定特定的监听器,我们可以使用 v-on:eventName="listeners.listenerName",其中 listenerName 是函数式组件的父级绑定的监听器:
<template functional>
<input
type="submit"
v-on:click="listeners.click"
v-bind="data.attrs"
/>
</template>
绑定到不存在的侦听器属性将导致错误。为了避免这种情况,我们可以使用 |
至此,我们学习了如何使用具有 .vue
组件模板变体和渲染函数的函数式组件来实现常见的 Vue.js 组件模式。
我们现在将构建一个待办事项应用程序,该应用程序使用我们在本章中讨论过的所有模式。
活动 5.01:使用插件和可重用组件构建 Vue.js 应用程序
在本活动中,我们将构建一个集成 jsonplaceholder 作为数据源的待办事项应用程序。
我们的待办事项应用程序将加载待办事项并将其显示为列表。它将根据待办事项是否已完成以及待办事项的名称显示一个复选框。
在核对待办事项时,应用程序会将其同步到应用程序接口(API)。
我们将注入 axios 作为插件来查询 https://jsonplaceholder.typicode.com 。
请按照以下步骤完成此活动:
-
将 axios 安装到项目中。
-
要将 axios 作为属性注入到此组件实例中,请创建一个 src/plugins/axios.js 插件文件,该文件在安装(install)时意味着组件实例具有 axios 属性。
-
要使插件正常工作,请将其导入并注册到 src/main.js 中。
-
我们还希望将 API 的 baseUrl 注入到所有组件中。我们将在 src/main.js 文件中创建一个内联插件来执行此操作。
-
我们现在想要从 src/App.vue 中获取所有待办事项。执行此操作的一个好地方是在 mounted 的生命周期方法中。
-
为了显示待办事项列表,我们将在 src/components/TodoList.vue 中创建一个 TodoList 函数式组件,该组件接收待办事项 prop,循环浏览项目,并将待办事项的渲染延迟到绑定了待办事项的待办事项范围槽下。
-
现在,我们可以使用 TodoList 组件来渲染我们已经在 src/App.vue 中获取的待办事项。
-
我们现在需要创建一个 TodoEntry 组件,我们将在其中实现大部分特定于待办事项的逻辑。对于组件来说,一个好的做法是让 props 非常具体地针对组件的角色。在本例中,我们要处理的 todo 对象的属性是 id、title 和 Completed,因此这些应该是我们的 TodoEntry 组件接收的 props。 我们不会将 TodoEntry 设为函数式组件,因为我们需要一个组件实例来创建 HTTP 请求。
-
然后,我们将更新 src/App.vue,以便它消耗 TodoEntry(确保绑定 id、title 和 completed)。
-
添加切换待办事项的完成(Complete)状态的功能。我们将在 src/components/TodoEntry.vue 中实现其中的大部分内容。我们将监听 input 更改事件。在更改时,我们需要读取新值并向
/todos/{todoId}
发送一个 PATCH 请求,其中包含一个包含已完成设置的新值的对象。我们还希望在 Vue.js 中发出 completedChange 事件,以便 App 组件可以更新内存中的数据。 -
在 App.vue 中,我们希望在触发 completeChange 时更新相关的待办事项。由于 completeChange 不包含待办事项的 ID,因此在设置 handleCompleteChange 函数以侦听 completeChange 时,我们需要从上下文中读取该 ID。
预期输出如下:

总结
在本章中,我们研究了全局组合模式和高级组件设置,它们可用于减少 Vue.js 应用程序中的重复。
首先,我们了解了 mixin,它显式地共享功能,同时让组件拥有最终发言权,并看到了此规则的例外情况。然后我们看到插件如何成为多个 Vue.js 原语的绝佳挂钩。
接下来,我们研究了规范模式如何最大化 Vue.js 中的组件可重用性。展示了一些想法,例如利用 props 来委托数据、插槽来委托模板,以及实现允许组件与 Vue 惯用速记方式(例如 v-model)一起使用的接口。
我们还深入研究了 .vue
文件之外的 Vue.js 组件。我们通过引入字符串模板、渲染函数和 JSX 以及每种工作方法的要求,深入研究了 Vue.js 组件是什么。 component 标签和 keep-alive 展示了另一种基于响应性数据在 Vue.js 应用程序中动态渲染组件的方法。最后,我们看到了函数式组件如何巩固我们如何使用 .vue
文件定义组件。
到目前为止,我们已经学习了如何使用组件、mixin 和插件来构建应用程序。为了构建跨多个页面的应用程序,我们需要实现路由。这就是我们将在下一章中解决的问题。