1️⃣ 函数式组件的优点
1️⃣ 函数式组件
当一个组件不需要状态(即响应式数据 data)、不需要任何生命周期场景、只接受一些 props 来显示组件时,我们可以将其标记为函数式组件。我们可以将组件标记为 functional,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。一个函数式组件就像这样
Vue.component('my-component', {
functional: true,
// 为了弥补缺少的实例
// 提供第二个参数作为上下文
render: function (createElement, context) {
// ...
}
})
partnerRedPacketLogExport() {
req.partnerRedPacketLogExport().then((res) => {
if (!res) return
const blob = new Blob([res], { type: 'text/csv' })
if (window.navigator.msSaveOrOpenBlob) { // 兼容IE10
navigator.msSaveBlob(blob, this.filename)
} else {
const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
const a = document.createElement('a') // 创建a标签
a.style.display = 'none'
a.href = href // 指定下载链接
a.download = '红包发放记录' // 指定下载文件名
a.click() // 触发下载
URL.revokeObjectURL(a.href) // 释放URL对象
}
})
}
在 2.5.0 及以上版本中,如果你使用了单文件组件,那么基于模板的函数式组件可以这样声明:
<template functional>
</template>
为了弥补缺少的实例,render 函数提供第二个参数 context 作为上下文。context 包括如下字段
1. **props:**提供所有 prop 的对象
2. **slots: **一个函数,返回了包含所有插槽(非作用域)的对象
3. **scopedSlots:** (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
4. **data:**传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
5. **parent:**对父组件的引用
6. **listeners: **(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
7. **injections: **(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。
8. **children: **VNode 子节点的数组,包含了所有的非作用域插槽和非具名插槽。
<script>
export default {
render(h, content) {
console.log(h);
const { props, children, slots, scopedSlots, data, parent, listeners, injections } = content;
return (
<div>
......
</div>
);
},
};
</script>
注意:在 2.3.0 之前的版本中,如果一个函数式组件想要接收 prop,则 props 选项是必须的。在 2.3.0 或以上的版本中,你可以省略 props 选项,所有组件上的 attribute 都会被自动隐式解析为 prop。 当使用函数式组件时,该引用将会是 HTMLElement,因为他们是无状态的也是无实例的。
2️⃣ slots() 和 children 对比
当 slots().defalut 使用了 #default 指定默认插槽后只有 template 中的标签会被渲染, 而 children 则会将所有非作用域插槽和非具名插槽的 VNode 子节点渲染