Vue函数式组件专篇深入分析
loyd3 人气:0函数式组件的实现相对容易。一个函数式组件本质上就是一个普通函数,该函数的返回值是虚拟DOM。
在用户接口层面,一个函数式组件就是一个返回虚拟DOM的函数,如下面的代码所示:
function MyFuncComp(props){ return {type:'h1',children: porps.title} }
函数式组件没有自身状态,但仍然可以接收由外部传入的props。为了给函数式组件定义props,需要在组件函数上添加静态的props属性,如下面代码所示:
function MyFuncComp(props){ return {type:'h1',children:props.title} } // 定义props MyFuncComp.props = { title: String }
在有状态组件的基础上,实现函数式组件将变得非常简单,因为挂载组件的逻辑可以复用mountComponent函数,为此,需要在patch函数内支持函数类型的vnode.type,如下面patch函数的代码所示:
function patch(n1,n2,container, anchor){ if(n1 && n1.type !== n2.type){ unmount(n1) n1 = null } const {type} = n2 if(typeof type === 'string'){ // 省略部分代码 }else if(type === Text) { // 省略部分代码 }else if(type === Fragment) { // 省略部分代码 }else if(type === 'object' || typeof type === 'function') { // component if(!n1){ mountComponent(n2,container,anchor) }else{ patchComponent(n1,n2,anchor) } } }
在patch函数内部,通过检测vnode.type的类型来判断组件的类型
- 如果vnode.type是一个对象,则它是一个有状态组件,并且vnode.type是组件选项对象;
- 如果vnode.type是一个函数,则它是一个函数式组件
下面是修改后的mountComponent函数,其支持挂载函数式组件:
function mountComponent(vnode,container,anchor){ // 检查是否是函数式组件 const isFunctional = typeof vnode.type === 'function' let componentOptions = vnode.type if(isFunctional){ // 如果是函数式组件,则将vnode.type作为渲染函数,将vnode.type.props作为props选项定义即可 componentOptions = { render:vnode.type, props: vnode.type.props } } // 省略部分代码 }
实现对函数式组件的兼容非常简单。首先,在mountComponent函数内检查组件的类型,如果是函数式组件,则直接将组件函数作为组件选项对象的render选项,并将组件函数的静态props属性作为组件的props选项即可。
当然,出于更加严谨的考虑,我们需要通过isFunctional变量实现选择性地执行初始化逻辑,
加载全部内容