【React】react-shadow原理(shadow-dom的探索)

前言

  • 突然对shadowdom感兴趣了,然后实现发现了很多坑,特此总结一下。

实现原理

  • 函数组件我实现的有点bug,就是子组件的自己的状态无法改变,暂时不清楚为啥,如果有需要可以看一下react-shadow的实现:https://github.com/Wildhoney/ReactShadow/blob/master/src/core/index.js#L19
  • 类组件实现起来倒是没啥问题:
export class ShadowView extends React.Component {
	state: {
		root: null | ShadowRoot;
		pdiv: null | HTMLDivElement;
		div: null | HTMLDivElement;
	} = {
		root: null,
		pdiv: null,
		div: null,
	};
	setRoot = (pdiv: HTMLDivElement) => {
		if (pdiv) {
			const div = document.createElement("div");
			const shadow = div.attachShadow({ mode: "open" });
			pdiv.appendChild(div);
			this.setState({ root: shadow, pdiv, div });
		}
	};

	componentWillUnmount() {
		if (this.state.pdiv && this.state.div) {
			this.state.pdiv!.removeChild(this.state.div);
			this.setState((pre) => ({ ...pre, root: null, div: null }));
		}
	}

	render() {
		const { children } = this.props;
		const { root } = this.state;
		return (
			<div ref={this.setRoot}>
				{root &&
					ReactDOM.createPortal(children, root as unknown as Element)}
			</div>
		);
	}
}

export function Axxx(props: { state: string; cl: Function }) {
	const [state, setState] = useState(0);
	return (
		<div className="aaa">
			xcsdsasdasdasdsad
			{props.state}
			{state}
			<button
				onClick={() => {
					setState((pre) => pre + 1);
					props.cl();
				}}
			>
				++++
			</button>
			<button
				onClick={() => {
					setState((pre) => pre - 1);
					props.cl();
				}}
			>
				---
			</button>
			<a>xxx</a>
		</div>
	);
}
export class App extends React.Component {
	state = { message: "..." };
	onBtnClick = () => {
		this.setState({ message: this.state.message + "xx" });
	};
	render() {
		return (
			<ShadowView>
				<Axxx state={this.state.message} cl={this.onBtnClick}></Axxx>
			</ShadowView>
		);
	}
}
export default App;
  • 主要是必须有一个shadowRoot,所以在每次更新时,会出现卸载问题,然后重新去给已有的shadowRoot附上shadow导致报错。在卸载时删掉即可。
  • 至于样式,需要那种服务端渲染的样式写法,或者内联样式,否则就是样式隔离。
  • 目前正常来说除了样式比较麻烦,事件状态什么的是都有的,等我再用一段时间看看还有啥问题。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

业火之理

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值