【Vue】在.vue文件中style是必须的吗?那script是必须的吗?为什么?——函数式组件
都不是必须的,如果是普通组件那么只能是一个静态html,如果是函数式组件, 那么可以直接使用props等函数式组件属性。
函数式组件
<anchored-heading :level="1"> <span>Hello</span> world! </anchored-heading>
这个锚点标题组件是比较简单的,没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法。实际上,它只是一个接受一些 prop 的函数。在这样的场景下,我们可以将组件标记为 functional
,这意味它无状态 (没有响应式数据),也没有实例 (没有 this
上下文)。一个函数式组件就像这样:
Vue.component('my-component', { functional: true, // Props 是可选的 props: { // ... }, // 为了弥补缺少的实例 // 提供第二个参数作为上下文 render: function (createElement, context) { // ... } })
注意:在 2.3.0 之前的版本中,如果一个函数式组件想要接收 prop,则 props
选项是必须的。在 2.3.0 或以上的版本中,你可以省略 props
选项,所有组件上的 attribute 都会被自动隐式解析为 prop。
当使用函数式组件时,该引用将会是 HTMLElement,因为他们是无状态的也是无实例的。
在 2.5.0 及以上版本中,如果你使用了单文件组件,那么基于模板的函数式组件可以这样声明:
<template functional> </template>
组件需要的一切都是通过 context
参数传递,它是一个包括如下字段的对象:
props
:提供所有 prop 的对象children
:VNode 子节点的数组slots
:一个函数,返回了包含所有插槽的对象scopedSlots
:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。data
:传递给组件的整个数据对象,作为createElement
的第二个参数传入组件parent
:对父组件的引用listeners
:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是data.on
的一个别名。injections
:(2.3.0+) 如果使用了inject
选项,则该对象包含了应当被注入的 property。
在添加 functional: true
之后,需要更新我们的锚点标题组件的渲染函数,为其增加 context
参数,并将 this.$slots.default
更新为 context.children
,然后将 this.level
更新为 context.props.level
。
因为函数式组件只是函数,所以渲染开销也低很多。
在作为包装组件时它们也同样非常有用。比如,当你需要做这些时:
- 程序化地在多个组件中选择一个来代为渲染;
- 在将
children
、props
、data
传递给子组件之前操作它们。
下面是一个 smart-list
组件的例子,它能根据传入 prop 的值来代为渲染更具体的组件:
var EmptyList = { /* ... */ } var TableList = { /* ... */ } var OrderedList = { /* ... */ } var UnorderedList = { /* ... */ } Vue.component('smart-list', { functional: true, props: { items: { type: Array, required: true }, isOrdered: Boolean }, render: function (createElement, context) { function appropriateListComponent () { var items = context.props.items if (items.length === 0) return EmptyList if (typeof items[0] === 'object') return TableList if (context.props.isOrdered) return OrderedList return UnorderedList } return createElement( appropriateListComponent(), context.data, context.children ) } })