Vue高级组件之函数式组件的使用场景与源码分析

yizhihongxing

下面是Vue高级组件之函数式组件的使用场景与源码分析的详细攻略:

什么是函数式组件?

函数式组件在Vue2.3版本中引入的新特性,可以提高组件的性能和减少不必要的组件实例化。它是一种纯函数,接受一个props对象并返回渲染的虚拟DOM。它没有状态(即数据驱动),也没有实例,所以没有生命周期函数,仅仅是一个接收props并返回渲染vnode的函数。使用函数式组件可以减少不必要的组件实例化,避免组件状态带来的性能开销,同时减少内部无状态组件的渲染次数。

下面是一个函数式组件的例子:

<template functional>
  <div class="functional-component">
    {{props.text}}
  </div>
</template>

函数式组件的使用场景

函数式组件通常用于以下场景:

  1. 只需要展示数据,不需要进行交互的组件。
  2. 高阶组件中的无状态组件。
  3. 当父组件需要多次使用某个组件时,可以把这个组件改成函数式组件,减少组件实例化次数。

通过使用函数式组件,可以大大提高Vue应用的整体性能。

函数式组件的源码分析

函数式组件在Vue源码中的实现过程如下:

  1. 创建函数式组件的VNode节点(函数式组件没有组件实例,因此没有VNode子树)。
  2. 获取函数式组件名,并将其添加到VNode的fnContext属性中。
  3. 将组件的props和children绑定到VNode的data属性中。
  4. 返回VNode作为函数式组件的渲染结果。由于函数式组件没有实例,因此不需要调用_render方法。

下面是一个更详细的源码分析:

// src/core/vdom/create-component.js

export function createFunctionalComponent (
  Ctor: Class<Component>,
  propsData: ?Object,
  data: ?VNodeData,
  contextVm: ?Component,
  children: ?Array<VNode>,
  tag?: string
): VNode | Array<VNode> {
  const props = {}
  const propOptions = Ctor.options.props
  // 将propsData转成props对象
  if (propsData !== undefined) {
    for (const key in propOptions) {
      props[key] = propsData[key]
    }
  }
  // 为VNode设置组件名和props
  const renderContext = new FunctionalRenderContext(props, data, contextVm, children, tag)
  const vnode = Ctor.options.render.call(null, renderContext._c, renderContext)
  // 设置fnContext属性
  vnode.fnContext = contextVm
  vnode.fnOptions = Ctor.options
  if (data.slot) {
    (vnode.data || (vnode.data = {})).slot = data.slot
  }
  // 将props和children绑定到data属性中
  return vnode
}

// src/core/vdom/create-functional-component.js

export class FunctionalRenderContext {
  // 构造函数
  constructor (
    props: any,          // props
    data: any,           // VNodeData
    parentVm: Component, // 父组件
    children: ?Array<VNode>,  // 子节点
    tag?: string          // 标签名
  ) {
    this.props = props
    this.data = data
    this.children = children
    this.parent = parentVm
    this.listeners = {}
    this.slots = () => resolveSlots(children, contextVm)
    this.scopedSlots = {}
    this.slots._ctx = contextVm
    this._c = (a, b, c, d) => createElement(contextVm, a, b, c, d, false)
  }
}

以上是函数式组件的实现过程,也就是说函数式组件的渲染和普通组件的渲染是有所不同的。

示范1:使用函数式组件进行布局优化

可以使用函数式组件进行布局优化,例如在一个列表中,每个item中有一段固定的文本,这段文本不需要重复渲染,可以使用函数式组件只渲染一次。示例如下:

在列表中使用函数式组件:

<template>
  <div>
    <ul>
      <li v-for="item in list" :key="item.id">
        <some-text :text="'固定文本'" />
        {{item.text}}
      </li>
    </ul>
  </div>
</template>

<script>
import SomeText from '@/components/SomeText.vue'

export default {
  components: {
    SomeText
  },
  data() {
    return {
      list: [
        {id: 1, text: 'item 1'},
        {id: 2,text: 'item 2'},
        ...
      ]
    }
  }
}
</script>

函数式组件具体实现:

<template functional>
  <div>{{props.text}}</div>
</template>

最终运行结果:整个列表只渲染了一次 <some-text> 组件,减少了渲染次数,提高了性能。

示范2:使用函数式组件进行性能优化

针对高阶组件(HOC)的优化,我们可以使用函数式组件优化,这样通过高阶组件渲染的无状态组件就会不会导致不必要的组件实例化,优化性能。

使用高阶组件:

<template>
  <div>
    <Button />
  </div>
</template>

<script>
import hoc from '@/hoc/Hoc'

export default {
  components: {
    Button: hoc(Button)
  }
}
</script>

高阶组件 HOC:

export default (WrappedComponent) => {
  return {
    functional: true,
    render(h, { data, children }) {
      return h(WrappedComponent, data, children)
    }
  }
}

以上便是 Vue 高级组件之函数式组件的使用场景与源码分析的攻略。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Vue高级组件之函数式组件的使用场景与源码分析 - Python技术站

(0)
上一篇 2023年5月28日
下一篇 2023年5月28日

相关文章

  • Vue ​v-model相关知识总结

    关于 Vue v-model 相关知识的总结,我可以分为以下几个部分进行讲解: 1. v-model 的作用 v-model 是 Vue 用于实现表单元素双向绑定的一个指令,主要作用是在输入和输出表单值时自动同步,省去了我们手动监听 input 事件和调用赋值方法去同步的繁琐过程。 2. 使用 v-model 的要求 在使用 v-model 时,需要满足以下…

    Vue 2023年5月27日
    00
  • Vue axios 中提交表单数据(含上传文件)

    当我们使用Vue.js和axios时,我们通常需要将表单数据提交到后端交给服务器处理。这包括一些简单的表单数据提交和上传文件. 这里提供一个完整攻略如何使用Vue.js和axios提交表单数据(包含上传文件)。 设置后端服务器接受表单数据和文件 首先,我们需要设置后端服务器接受表单数据和文件,并且返回响应结果。通常情况下,我们会使用一些服务器端框架例如Dja…

    Vue 2023年5月28日
    00
  • vue项目中使用bpmn-自定义platter的示例代码

    下面我将详细讲解如何在Vue项目中使用BPMN自定义platter的完整攻略。 准备工作 首先,我们需要在Vue项目中安装相应的依赖项。打开终端(Terminal),进入到Vue项目的根目录下,然后执行以下命令: npm install bpmn-js bpmn-moddle bpmn-js-properties-panel 这三个依赖项分别是: bpmn-…

    Vue 2023年5月28日
    00
  • 关于vue3中setup函数的使用

    下面开始讲解关于Vue3中setup函数的使用的完整攻略。 一、什么是setup函数 setup是Vue3中引入的全新选项,它是组件实例化之前最先执行的一个函数。Vue3中设计setup函数的目的是要取代Vue2中的data、created、beforeCreate三个选项,将它们的功能都整合在setup函数中。新的API可以更好地应对TS等类型化语言的需求…

    Vue 2023年5月28日
    00
  • 为什么vue中不建议使用空字符串作为className

    在Vue中使用类名时,应尽量避免空字符串作为类名,以下是原因及解决方案: 1. 空字符串无法清除类名 在Vue中使用 v-bind:class 绑定类名时,空字符串会被视为有效的类名。当我们通过更改 data 中的属性值来更改类名时,空字符串也会作为一个类名被添加。但是,一旦添加上了空字符串,就无法通过更改该属性值来清除这个空字符串类名。 示例代码: &lt…

    Vue 2023年5月27日
    00
  • 详解vue.js组件化开发实践

    详解Vue.js组件化开发实践 Vue.js是一款简单易用,功能十分强大的前端框架,其中组件化开发是Vue的一大特点,本文将详细讲解Vue.js组件化开发实践的完整攻略。 为什么要使用组件化开发 组件化开发是将页面拆分成不同的功能块,每个块独立封装成一个组件,从而实现重复利用和减少代码耦合,提高开发效率和维护性。在大型项目中使用组件化开发将十分必要。 组件化…

    Vue 2023年5月27日
    00
  • javascript 导出数据到Excel(处理table中的元素)

    下面是详细讲解“javascript 导出数据到Excel(处理table中的元素)”的完整攻略,过程中将包含两个示例说明。 1. 简介 在 web 开发中,有时需要将 table 数据导出为 Excel 文件。本文将介绍如何使用纯 javascript 处理 table 中的元素,并将 table 数据导出为 Excel 文件。 2. 代码实现 首先,我们…

    Vue 2023年5月28日
    00
  • Vue3初始化如何调用函数

    Vue3的初始化过程是在 createApp 函数中完成的。在这个函数中,可以调用一些辅助函数来进行初始化操作,例如创建根组件、挂载到DOM等。若要在初始化过程中调用函数,可以使用 beforeCreate 生命周期函数或者 setup() 函数。 使用 beforeCreate 生命周期函数 beforeCreate 生命周期函数是在组件创建之前被调用的,…

    Vue 2023年5月27日
    00
合作推广
合作推广
分享本页
返回顶部