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日

相关文章

  • 浅析vue中的provide / inject 有什么用处

    提供/注入(Provide / Inject)是Vue.js中的一个高级特性,允许祖先组件通过一个透明的接口向后代组件注入依赖项。在这个过程中,依赖注入是通过一个专用的上下文对象进行的。这种上下文对象作为依赖被传递到了需要访问依赖的子组件中。本攻略将介绍Vue中provide/inject的用处、使用方法以及示例说明。 使用方法 在祖先组件中,使用provi…

    Vue 2023年5月29日
    00
  • vue实现前端展示后端实时日志带颜色示例详解

    Vue实现前端展示后端实时日志带颜色示例详解 介绍 本攻略通过Vue.js实现前端实时展示后端日志功能的实现方法,并且可以根据日志级别实时修改展示的颜色,提高可读性。 实现过程 前端代码部分 首先,在template中建立一个<div>用于展示后端传送过来的实时日志,根据控制台输出的日志可以推断,后端传来的数据都以字符串形式存在,并且每个日志信息…

    Vue 2023年5月27日
    00
  • vue发送ajax请求详解

    下面我来为大家详细讲解vue发送ajax请求的完整攻略。 一、什么是ajax请求? Ajax,全称为Asynchronous Javascript And XML,即异步的Javascript和XML技术,是一种在不刷新整个页面的情况下与服务器进行数据交互的技术。一般来说,我们发送Ajax请求是为了从服务器获取数据或提交数据到服务器。 二、Vue发送ajax…

    Vue 2023年5月28日
    00
  • 解决vue vite启动项目报错ERROR: Unexpected “\x88“ in JSON 的问题

    如果你在使用vue vite启动项目时遇到了JSON解析异常,有可能是因为项目依赖项中某个文件含有非utf-8编码的字符而导致的。 解决此问题的方法如下: 在项目的根路径下创建vite.config.js文件,如果该文件已存在则直接修改它,如果没有请参照以下示例内容创建该文件。 const { createServer } = require("v…

    Vue 2023年5月28日
    00
  • vue导出word纯前端的实现方式

    让我为您详细讲解一下“Vue导出Word纯前端的实现方式”的攻略。 1. 前置条件 在开始实现前,我们需要安装一些 npm 包和一些必备的工具,这些工具和包的详情如下: DocxTemplater:一个用于生成 docx 文档的工具 FileSaver.js:一个用于前端文件下载的 JS 库 Blob.js:一个 Blob 对象的 polyfill,用于处理…

    Vue 2023年5月27日
    00
  • until封装watch常用逻辑简化代码写法

    我来详细讲解一下“until封装watch常用逻辑简化代码写法”的攻略。 什么是until until是Vue.js中一个常用的指令修饰符,它用于监听数据变化直到满足条件才执行操作。常用语法如下: <!– 监听value值变化,直到其等于一个值为9的时候才执行alert方法 –> <div v-on:click="alert(…

    Vue 2023年5月27日
    00
  • Vuejs开发环境搭建及热更新【推荐】

    Vuejs开发环境搭建及热更新攻略 1. 安装Node.js和npm 在开始Vuejs的开发之前,我们需要先安装Node.js。这是一款基于Chrome V8引擎的JavaScript运行环境。 在安装Node.js的时候,会自动安装npm,npm是一个可以解决Node.js插件之间依赖的包管理器。可以通过这个命令来检查是否安装成功: node -v //查…

    Vue 2023年5月28日
    00
  • 关于Vue 监控数组的问题

    关于Vue 监控数组的问题,我们可以通过 Vue 中的 computed 属性和 watch 属性来完成监控数组的操作。 监听数据的变化 Vue 提供了一种方法,以便自动跟踪数组的变化。这个方法是使用 Vue.set 或者是修改数组的长度来改变数组变化。在这个方法之后,组件会自动地更新记录数组。在实际应用中,我们常常使用 Array.push()、Array…

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