什么是函数式组件?

我们可以把函数式组件想象成组件里的一个函数,入参是渲染上下文(render context),返回值是渲染好的HTML

对于函数式组件,可以这样定义:

  • Stateless(无状态):组件自身是没有状态的
  • Instanceless(无实例):组件自身没有实例,也就没有this

由于函数式徐建拥有拥有这两个特性,我们就可以把它用作高阶组件(High order components),所谓高阶,就是可以生成其他组件的组件。

函数式组件的特点

  • 没有管理任何状态
  • 没有监听任何传递给它的状态
  • 没有生命周期方法
  • 只接收一些prop的函数

函数式组件的优点

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

为什么要使用函数式组件

速度快

因为函数式组件没有状态,所以我们不需要像vue的响应式 系统一样需要经过额外的 初始化。

函数式组件任然会对响应的变化 做出响应式变化,比如新传入props,但是在组件本身中,它无法知道数据什么时候发生变化,因为它不维护自身状态。

对于大型应用程序,在使用函数式组件之后,你会看到DOM的渲染和更新会有很大的改进。

函数式组件的适用场景

函数式组件可能不适用很多情况。因为使用JavaScript框架的目的是构建响应式的应用程序

适用场景:

  • 一个简单的展示组件,也就是所谓的dumb组件,例如button组件,pills,tags,cards,甚至整个页面都是静态文本,比如about页面
  • “高阶组件”用于接收一个组件作为参数,返回一个被包装过的组件
  • v-for循环中每项通常都是很好的候选项。

functional:true加上render function,就是一个简单的函数式组件了

demo:

创建一个functionButton.js的函数式组件:

export default {
    name: 'functional-button',
    functional: true,
    render(createElement, context) {
        return createElement('button', 'click me')
    }
}

函数式组件没有this,参数就靠context来传递

context的属性:

  • props
  • children
  • slots(a slots object)
  • parent
  • listeners
  • injections
  • data

其中上面的data包含了其他属性的引用,nibility。

现在创建一个App.vue来引入上面的函数式组件

<template>
    <FunctionalButton>
        click me
    </FunctionButton>
</template>

上面的click me就是FunctionButton.js的children属性,我们可以把组件改造下,有App.vue来定义组件的button按钮

export default {
    name: 'funtional-button',
    functional: true,
    render(createElement, { children }) {
        return createElement('button', children)
    }
}

上面用了ES6参数的解构,用{children}来代替context

事件定义

函数式组件没有实例,事件只由父组件传递。下面在app.vue上定义一个最简单的click事件。

<template>
  <FunctionalButton @click="log">
    Click me
  </FunctionalButton>
</template>

对应的functionButton.js

export default {
  functional: true,
  render(createElement, { props, listeners, children }) {
    return createElement(
      'button',
      {
        attrs: props,
        on: {
          click: listeners.click
        }
      },
      children
    );
  }
};

简单写法

vue中设计的api比较人性化,我们可以将props、listeners统一集中在data中。

export default {
  functional: true,
  render(createElement, { data, children }) {
    return createElement( 'button', data, children );
  }
};
createElement('button', data, ['hello', ...children])

 

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐