随处可见
指令式渲染经常在项目和组件库中被使用,比如: antd 的 message、antd-mobile 的 ImageViewer 等组件都支持这种方式,相信大家多少都接触过。
message.success('hello world!') // antd
ImageViewer.show({ image: demoImage,}) // antd-mobile
优点
由于与我们常见组件式的渲染方式不同,它有以下优点:
- 灵活,无需在组件中 return JSX 也能在页面渲染,可以在事件回调中调用。
- 方便,对于使用者来说无需增加额外的状态来控制元素显隐
实现原理
在body中创建的新DOM元素,然后以该元素为container,渲染出新的react组件实例,然后再适当的时候(用户点击操作、几秒过后等时机)销毁该react组件实例和DOM元素。
核心逻辑简单实现
import { createRoot } from "react-dom/client";
export default function directiveRender (reactEle) {
const container = document.createElement("div");
document.body.append(container);
const root = createRoot(container);
root.render(reactEle); // 组件渲染
return function destroy() {
root.unmount();
container.remove();
};
}
该函数接收一个react元素并渲染到body新插入的div里面,最后返回一个销毁该元素的函数。
ps: demo代码使用 React18 的 createRoot , 低于该版本请使用 ReactDOM.render 、unmountComponentAtNode
完整demo: codesandbox.io/s/zhi-ling-…
参考:
要在vue实现的话,原理是一致的。