# SCF还是JSX
之前不怎么思考这类的问题,长期使用 vue开发的过程中,也没觉得不爽的地方,可能是因为接触比较多的是业务代码和移动端开发
之所以会有这样的思考,是因为后来接触了使用 VUE 开发 PC 后台,PC 的项目的特点就是页面需要承载的内容非常多,所以业务也相对比较复杂,当内容越来越多时,为了减肥就会去抽离成组件的方法进行组装页面,封装得越多彼此的通信越多,用到的 slot
,mininx
的地方也越多,这个时候就越来越感觉到项目好难看得明白
这就是会思考题目的来源
# SFC
SFC 即 Single File Component,也即单文件组件,Vue 组件就是很明显的SFC
一个vue组件包含了模板和Vue api和样式,一个组件的功能及包装的代码非常得完整用也一目了然,这也是一直都觉得使用 vue 非常舒服的原因,队了这些 Vue 使用 SFC 还以下优点:
通过对模板的分析,可以做一些前期优化,这点是JSX语法很难以做到的
例如“静态树提升”优化:
如下一段模板(这是模板,并非JSX):
<template>
<div>
<span>static</span>
<span>{{ dynamic }}</span>
</div>
</template>
如果不做任何优化,那么编译后得到的代码应该是这样子:
render() {
return h('div', [
h('span', 'static'),
h('span', this.dynamic)
]);
}
那么每次重新渲染时,都会执行3次 h 方法,虽然未必会触发真正的DOM更新,但这也是一部分开销。
通过观察,我们知道 h('span', 'static') 这段代码传入的参数始终都不会有变化,它是静态的,而只有 h('span', this.dynamic) 这段才会根据 dynamic 的值变化。
在Vue 3.0中,编译器会自动分析出这种区别,对于静态的节点,会自动提升到 render 方法外部,避免重复执行。
Vue 3.0编译后的代码:
const __static1 = h('span', 'static');
render() {
return h('div', [
__static1,
h('span', this.dynamic)
])
}
这样每次渲染时就只会执行两次 h 。换言之,经过静态树提升后,Vue 3.0渲染成本将只会和动态节点的规模相关,静态节点将会被复用。
除了静态树提升,还有很多别的编译阶段的优化,这些都是JSX语法难以做到的,因为JSX语法本质上还是在写JS,它没有任何限制,强行提升它会破坏JS执行的上下文,所以很难做出这种优化(也许配合 prepack 可以做到)。
考虑到这一点,如果你是在实现一个对性能要求较高的基础组件库,那模板语法仍然是首选。
另外JSX也没办法做 ref 自动展开,使得 ref 和 reactive 在使用上没有太大区别。
# SFC的问题
以VUE 为便,当一个组件开发变得复杂的时候可能会出现以下问题:
组件扩展节点
vue中如在一个组件中希望能显示外部自定义的节点时,需要使用 slot, slot 这个东西每次用都觉得便扭,便扭的原因是其绕来绕去的作用域
同样的功能在 react 中实现就比较直观
const Comp = () => <Layout header={<MyHeader />} footer={<MyFooter />} />
或者将函数组件当作参数往别个函数组件中传,这种写法更符合咱们的常规思维
组件要注册才能用
vue 要使用组件,必需先注册该组件,如果想绕过注册这一步,只能使用渲染函数
minxin
这个就是自己用得爽,看别人就是不爽的东西
组件通信
同层级且组件通信少的情况下还好,一旦组件数量变多且出现深层组件通信时,简直噩梦,当然这应该不是只有 vue 才会出现的问题
JSX 本质上就是一个函数,应用的组成就是 函数彼此调用的过程,可以灵活得使用 JS 做任何事情,所以在做 公共组件,以及高度灵活的组件时,使用 JSX 将更方便
日后在 VUE3项目中中 会尝试使用 JSX和SFC 结合的方法,具体感觉一下开发体验是否有改善