我们知道 vue3 的到来,极大提升了vue的编译效率,一个重要的原因是采用了静态提升策略编译模版。静态提升是指,将模板中静态的内容标记出来,下次更新模板时,跳过diff阶段以此来提升渲染速度。
<div>
<div>foo</div> <!-- 需提升 -->
<div>bar</div> <!-- 需提升 -->
<div>{{ dynamic }}</div>
</div>
那么react是否有类似的功能呢?坏消息是没有,好消息是可以通过babel插件实现。react中如果jsx片段不依赖任何状态,那么可以定义为是静态的。比如,一个简单的jsx文件如下:定义了一个Hr组件,和一个包含Hr组件的WithChildren组件。它们都是静态的。
const Hr = () => {
return <hr className="hr" />;
};
// 堆代码 duidaima.com
const WithChildren = (props) => {
return <div className={props.className}>
<hr />
</div>;
}
使用 jsx 方法解析成js文件后这样的:
import { jsx as _jsx } from "react/jsx-runtime";
const Hr = () => {
return _jsx("hr", {
className: "hr"
});
};
const WithChildren = props => {
return _jsx("div", {
className: props.className,
children: _jsx("hr", {})
});
};
我们可以看到,即使我们已经生成了Hr组件,在生成WithChildren组件时,又重新生成了一次Hr组件,也就是类似于vue2没有静态提升的效果。那么,我们应该怎么实现静态提升的效果呢?一个简单的想法立马浮现在了脑海里:短路符 ||
let val = null;
function createVal (val) {
if (!val) {
val = "your val"
}
return val
}
return val || createVal(val)
如果在上面的react示例中实现则如下:
var _hr, _hr2;
import { jsx as _jsx } from "react/jsx-runtime";
const Hr = () => {
return _hr || (_hr = _jsx("hr", {
className: "hr"
}));
};
const WithChildren = props => {
return _jsx("div", {
className: props.className,
children: _hr2 || (_hr2 = _jsx("hr", {}))
});
};
实际上,这是bable插件@babel/plugin-transform-react-constant-elements的工作原理,更好的消息是,这个插件也是@babel/preset-react的预设插件,默认是开启的。
好了,今天的分享就到这了,希望可以帮助到你。