聊聊 Vue2 中的 functional 组件

前言

最近组内有一个分享提到了 Vue2 的 functional 组件,大致上是说这个东西没有生命周期,在渲染层面上,会减少很多的消耗,一番处理之后,首屏时间和内存都能减少不少。

由此,我打算来好好学一下挖一下这个知识点。

functional 组件是什么?

Vue.js 中的 functional 函数化组件是一种特殊类型的无状态组件,它不依赖于内部状态,只依赖于传入的 props。这种组件没有实例,也就是说它们没有 this 上下文。函数化组件的主要特点如下:

  1. 无状态:函数化组件不包含响应式数据或内部状态,它们只依赖于传入的 props。
  2. 无实例:函数化组件没有实例,因此没有 this 上下文。
  3. 更高的性能:由于没有实例和响应式数据,函数化组件的渲染性能更高,适用于频繁更新的场景。
  4. 简洁的定义:函数化组件使用 render 函数定义,不需要完整的 Vue 组件选项对象。

函数化组件的定义示例:

ts 复制代码
Vue.component('my-functional-component', {
  functional: true,
  props: {
    message: {
      type: String,
      required: true
    }
  },
  render: function (createElement, context) {
    return createElement('div', context.props.message);
  }
});

functional函数化组件做比对是深度比对,会对对象深入的做对比,不是浅比较:

如果 props 对象外部不变,但内部的参数发生变化,函数化组件会重新渲染。因为函数化组件是无状态的,它们只依赖于传入的 props。当 props 的内部参数发生变化时,Vue 会检测到这些变化并重新渲染函数化组件。

ts 复制代码
Vue.component('my-functional-component', {
  functional: true,
  props: {
    userInfo: {
      type: Object,
      required: true
    }
  },
  render: function (createElement, context) {
    return createElement('div', context.props.userInfo.name);
  }
});

特点

1.functional 函数化组件本身无 watch/computed ,这就导致我们不能像在普通 Vue 组件中那样使用 watchcomputed 属性来监听参数变化。因为函数化组件没有实例和响应式数据,它们只依赖于传入的 props。当 props 发生变化时,函数化组件会自动重新渲染。

如果我们想要监听怎么办?

比较可行的办法是:在父组件中监听 props 变化,并在适当的时机传递新的 props 给函数化组件。这样,函数化组件会在接收到新的 props 时自动重新渲染。

2.functional 函数化组件本身无实例,这会导致如下后果:

  • 在函数化组件中,无法使用 this 访问组件实例,因为它们没有实例。
  • 由于没有实例,函数化组件无法使用 Vue 实例的方法和属性,例如 $emit$watch$refs 等。
  • 函数化组件没有实例,因此无法使用生命周期钩子函数,如 createdmountedupdated 等。
  • 函数化组件没有响应式数据和内部状态,它们只依赖于传入的 props。这意味着我们无法在函数化组件中使用 datacomputedwatch 等选项。
  • 在函数化组件中,我们需要通过 context 对象访问插槽(slots)和作用域插槽(scoped slots),而不是使用 this.$slotsthis.$scopedSlots

使用如下:

ts 复制代码
Vue.component('my-functional-component', {
  functional: true,
  props: {
    message: {
      type: String,
      required: true
    }
  },
  render: function (createElement, context) {
    // 访问 props
    const message = context.props.message;
    // 访问插槽
    const slots = context.slots();
    const defaultSlot = slots.default;
    // 访问作用域插槽
    const scopedSlots = context.scopedSlots;
    const customSlot = scopedSlots.customSlot;
    // 访问事件监听器
    const listeners = context.listeners;
    const clickListener = listeners.click;
});
相关推荐
你挚爱的强哥31 分钟前
✅✅✅【Vue.js】sd.js基于jQuery Ajax最新原生完整版for凯哥API版本
javascript·vue.js·jquery
y先森1 小时前
CSS3中的伸缩盒模型(弹性盒子、弹性布局)之伸缩容器、伸缩项目、主轴方向、主轴换行方式、复合属性flex-flow
前端·css·css3
前端Hardy1 小时前
纯HTML&CSS实现3D旋转地球
前端·javascript·css·3d·html
susu10830189111 小时前
vue3中父div设置display flex,2个子div重叠
前端·javascript·vue.js
IT女孩儿2 小时前
CSS查缺补漏(补充上一条)
前端·css
吃杠碰小鸡3 小时前
commitlint校验git提交信息
前端
虾球xz4 小时前
游戏引擎学习第20天
前端·学习·游戏引擎
我爱李星璇4 小时前
HTML常用表格与标签
前端·html
疯狂的沙粒4 小时前
如何在Vue项目中应用TypeScript?应该注意那些点?
前端·vue.js·typescript
小镇程序员4 小时前
vue2 src_Todolist全局总线事件版本
前端·javascript·vue.js