什么是函数式组件

  1. 可以把函数式组件想象成组件里的一个函数,入参是渲染上下文(render context),返回值是渲染好的 HTML;
  2. 对于函数式组件,可以这样定义:
    • Stateless(无状态):组件自身是没有状态的;
    • Instanceless(无实例):组件自身没有实例,也就没有 this;
  3. 函数式组件仍然会对响应的变化做出响应式变化,比如新传入props,但是在组件本身中,它无法知道数据什么时候发生变化,因为它不维护自身状态;

函数式组件的特点

  1. 没有管理任何状态;
  2. 没有监听任何传递给它的状态;
  3. 没有生命周期方法;
  4. 只接收一些 prop 的函数;
  5. 渲染开销低,因为函数式组件只是函数;

使用场景

  1. 一个简单的展示组件;
  2. “高阶组件”用于接收一个组件作为参数,返回一个被包装过的组件;
  3. v-for 循环中每项通常都是很好的候选项;
export default {
  name: 'router-link',
  functional: true, // 函数式组件,函数不用 new,没有 this,没有生命周期,没有数据 data 
  props: {
    to: {
      type: String,
      required: true
    },
    tag: {
      type: String
    }
  },
  render(h, context) {
    let tag = context.tag || 'a';
    const clickHandler = () => { // 指定跳转方法
      context.parent.$router.push(context.props.to);
      // 调用 $router 中的 push 方法进行跳转
    }
    return h(tag, {
      on: {
        click: clickHandler
      },
    }, context.slots().default);
  }
}

案例:router-view

export default {
  name: 'router-view',
  functional: true,  
  render(h, context) { // h => createElement,context 是 vm 实例
    // parent:当前父组件,data:<router-view a='1' b="2"/>上的一些标识(a、b 是 data里面的)
    let { parent, data } = context; 

    // 每个 vm 实例都有 $route.matched,依次的将他赋予到对应的 router-view 上
    let { matched } = parent.$route; 

    let depth = 0; // 判断当前组件是第几层组件,eg:第一层则取 matched[1]
    // 标识路由属性,渲染<router-view/>后设置 routerView 为 true,表示渲染完成
    data.routerView = true; 

    while (parent) {
      // $vnode 是 <hello-world/> 这个自定义组件的虚拟 dom
      // _vnode 是 <hello-world/> 这个自定义组件里面的 sfc 的内容的虚拟 dom
      if (parent.$vnode && parent.$vnode.data.routerView) {
        depth++; // 若存在父亲则 depth++,一直向上查找
      }
      parent = parent.$parent;
    }
    let record = matched[depth];
    if (!record) return h(); // 渲染一个空元素

    return h(record.component, data)
  }
}
打赏作者
您的打赏是我前进的动力
微信
支付宝
评论

中午好👏🏻,我是 ✍🏻   疯狂 codding 中...

粽子

这有关于产品、设计、开发的问题和看法,还有技术文档和你分享。

相信你可以在这里找到对你有用的知识和教程

了解更多

目录

  1. 1. 什么是函数式组件
  2. 2. 函数式组件的特点
  3. 3. 使用场景
  4. 4. 案例:router-link
  5. 5. 案例:router-view