1️⃣ 函数式组件的优点

渲染开销低,因为函数式组件只是函数

1️⃣ 函数式组件

当一个组件不需要状态(即响应式数据 data)、不需要任何生命周期场景、只接受一些 props 来显示组件时,我们可以将其标记为函数式组件。我们可以将组件标记为 functional,这意味它无状态 (没有响应式数据),也没有实例 (没有 this 上下文)。一个函数式组件就像这样

  1. Vue.component('my-component', {
  2. functional: true,
  3. // 为了弥补缺少的实例
  4. // 提供第二个参数作为上下文
  5. render: function (createElement, context) {
  6. // ...
  7. }
  8. })
  9. partnerRedPacketLogExport() {
  10. req.partnerRedPacketLogExport().then((res) => {
  11. if (!res) return
  12. const blob = new Blob([res], { type: 'text/csv' })
  13. if (window.navigator.msSaveOrOpenBlob) { // 兼容IE10
  14. navigator.msSaveBlob(blob, this.filename)
  15. } else {
  16. const href = URL.createObjectURL(blob) // 创建新的URL表示指定的blob对象
  17. const a = document.createElement('a') // 创建a标签
  18. a.style.display = 'none'
  19. a.href = href // 指定下载链接
  20. a.download = '红包发放记录' // 指定下载文件名
  21. a.click() // 触发下载
  22. URL.revokeObjectURL(a.href) // 释放URL对象
  23. }
  24. })
  25. }

在 2.5.0 及以上版本中,如果你使用了单文件组件,那么基于模板的函数式组件可以这样声明:

  1. <template functional>
  2. </template>

为了弥补缺少的实例,render 函数提供第二个参数 context 作为上下文。context 包括如下字段

  1. 1. **props:**提供所有 prop 的对象
  2. 2. **slots: **一个函数,返回了包含所有插槽(非作用域)的对象
  3. 3. **scopedSlots:** (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
  4. 4. **data:**传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
  5. 5. **parent:**对父组件的引用
  6. 6. **listeners: **(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
  7. 7. **injections: **(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。
  8. 8. **children: **VNode 子节点的数组,包含了所有的非作用域插槽和非具名插槽。
  1. <script>
  2. export default {
  3. render(h, content) {
  4. console.log(h);
  5. const { props, children, slots, scopedSlots, data, parent, listeners, injections } = content;
  6. return (
  7. <div>
  8. ......
  9. </div>
  10. );
  11. },
  12. };
  13. </script>

注意:在 2.3.0 之前的版本中,如果一个函数式组件想要接收 prop,则 props 选项是必须的。在 2.3.0 或以上的版本中,你可以省略 props 选项,所有组件上的 attribute 都会被自动隐式解析为 prop。 当使用函数式组件时,该引用将会是 HTMLElement,因为他们是无状态的也是无实例的。

2️⃣ slots() 和 children 对比

当 slots().defalut 使用了 #default 指定默认插槽后只有 template 中的标签会被渲染, 而 children 则会将所有非作用域插槽和非具名插槽的 VNode 子节点渲染
image.png