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

下面是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日

相关文章

  • 带你熟练掌握Vue3之Pinia状态管理

    带你熟练掌握Vue3之Pinia状态管理攻略 什么是Pinia? Pinia 是一个由 Eduardo San Martin Morote (Vue.js 核心团队成员)开发的 Vue.js3 状态管理库。 相较于 Vuex,在语法上有了很多的优化和改进,个人认为更易于学习使用,这里我们就来看一下如何使用它。 安装 在使用 Pinia 之前,需要确保先安装 …

    Vue 2023年5月27日
    00
  • vue组件间传值的方法你知道几种

    当我们使用Vue.js框架时,组件和组件间的通信常常需要使用传值方法来完成。下面将介绍Vue组件间传值的多种方法。 Props Props是Vue中一种父子组件传递数据的方式。父组件可以通过标签属性的形式把数据传递给子组件,子组件通过props来接收这些数据。 例如,父组件中这样写: <template> <div> <chil…

    Vue 2023年5月28日
    00
  • vue中计算属性computed理解说明包括vue侦听器,缓存与computed的区别

    让我们来详细讲解一下Vue中的计算属性computed。 计算属性computed 计算属性computed是Vue中常用的一个属性,它可以计算出新的值。在Vue中,当多个属性相关联时,我们可以使用计算属性computed来进行复杂的计算。 计算属性的使用 在Vue组件中使用计算属性computed,需要在Vue实例中添加computed属性,并返回一个新的…

    Vue 2023年5月27日
    00
  • Vue watch 侦听对象属性详解

    Vue Watch 侦听对象属性详解 介绍 Vue 中的 Watch 是一个非常有用的功能,它可以监听指定的数据变化,并在变化时执行一些逻辑代码。Watch 可以观察对象、数组和深层嵌套的属性。Watch 是一个特别强大的工具,有了它我们可以方便地做一些数据监控、校验以及一些逻辑的触发等操作。在本篇文章中,我们会详细地介绍如何使用 Vue 的 Watch 模…

    Vue 2023年5月28日
    00
  • Vue.js中v-for指令的用法介绍

    Vue.js中v-for指令的用法介绍 在Vue.js中,v-for指令用于在模板中循环渲染一个数组或对象的数据。它的基本语法如下: <div v-for="(item, index) in items" :key="index"> {{ index }} – {{ item }} </div>…

    Vue 2023年5月27日
    00
  • 详解vue中$nextTick和$forceUpdate的用法

    详解vue中$nextTick和$forceUpdate的用法 1. $nextTick的用法 1.1 作用 $nextTick是Vue中提供的异步方法,用于在下次DOM更新循环结束之后执行延迟回调,在修改数据之后立即使用这个方法,可以获取更新后的DOM。 示例代码: <template> <div> <h2>{{ mes…

    Vue 2023年5月29日
    00
  • vue iview组件表格 render函数的使用方法详解

    Vue iView组件表格 render函数的使用方法详解 什么是 render 函数 在 Vue 中,render 函数是用来生成虚拟 DOM 的函数,它可以根据数据生成对应的 HTML 结构,并最终生成真实的 DOM 节点。 为什么需要 render 函数 在使用 iView 表格组件时,我们需要通过传入 columns、data 等参数来生成表格的列和…

    Vue 2023年5月28日
    00
  • Vuejs从数组中删除元素的示例代码

    当我们在Vuejs中使用数组时,有时需要删除内部的元素。在本文中,我们将讨论如何使用Vuejs从数组中删除元素的示例代码。 示例1:使用Vuejs的原生方法splice删除元素 Vuejs中可以使用JavaScript原生方法splice()从数组中删除元素。 这个方法接受两个参数,一个是开始的索引,另一个是要删除的元素数量。 // 假设我们有一个数组如下:…

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