解决portal root入栈顺序问题
This commit is contained in:
parent
530fb24289
commit
ca3addf9fe
|
@ -286,4 +286,98 @@ describe('PortalComponent Test', () => {
|
||||||
dispatchChangeEvent(inputRef.current, 'test');
|
dispatchChangeEvent(inputRef.current, 'test');
|
||||||
expect(fn).toHaveBeenCalledTimes(1);
|
expect(fn).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('portal场景下,portal下元素点击事件冒泡到父元素', () => {
|
||||||
|
class Dialog extends Inula.Component {
|
||||||
|
node;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.node = window.document.createElement('div');
|
||||||
|
window.document.body.appendChild(this.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return Inula.createPortal(this.props.children, this.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn = jest.fn();
|
||||||
|
const subRef = Inula.createRef();
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div onClick={fn}>
|
||||||
|
<Dialog>
|
||||||
|
<div ref={subRef}/>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Inula.render(<App />, container);
|
||||||
|
Inula.act(() => {
|
||||||
|
subRef.current.dispatchEvent(new Event('click', { bubbles: true }));
|
||||||
|
});
|
||||||
|
expect(fn).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('portal嵌套场景下事件委托', () => {
|
||||||
|
class Dialog extends Inula.Component {
|
||||||
|
node;
|
||||||
|
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.node = window.document.createElement('div');
|
||||||
|
window.document.body.appendChild(this.node);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return Inula.createPortal(this.props.children, this.node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn = jest.fn();
|
||||||
|
const inputRef = Inula.createRef();
|
||||||
|
let value = '';
|
||||||
|
const onChange = (evt) => {
|
||||||
|
value = evt.target.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
let showSubPortal = () => {};
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Dialog>
|
||||||
|
<input onChange={fn}></input>
|
||||||
|
<Sub />
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function Sub() {
|
||||||
|
const [show, setShow] = Inula.useState(false);
|
||||||
|
showSubPortal = setShow;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{
|
||||||
|
show &&
|
||||||
|
<Dialog>
|
||||||
|
<input ref={inputRef} onChange={onChange}></input>
|
||||||
|
</Dialog>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
Inula.render(<App />, container);
|
||||||
|
Inula.act(() => {
|
||||||
|
showSubPortal(true);
|
||||||
|
});
|
||||||
|
dispatchChangeEvent(inputRef.current, 'test');
|
||||||
|
expect(value).toEqual('test');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -244,17 +244,22 @@ export function calcStartUpdateVNode(treeRoot: VNode) {
|
||||||
// 在局部更新时,从上到下恢复父节点的context和PortalStack
|
// 在局部更新时,从上到下恢复父节点的context和PortalStack
|
||||||
function recoverTreeContext(vNode: VNode) {
|
function recoverTreeContext(vNode: VNode) {
|
||||||
const contextProviders: VNode[] = [];
|
const contextProviders: VNode[] = [];
|
||||||
|
const portalRoots: VNode[] = [];
|
||||||
let parent = vNode.parent;
|
let parent = vNode.parent;
|
||||||
while (parent !== null) {
|
while (parent !== null) {
|
||||||
if (parent.tag === ContextProvider) {
|
if (parent.tag === ContextProvider) {
|
||||||
contextProviders.unshift(parent);
|
contextProviders.unshift(parent);
|
||||||
|
} else if (parent.tag === DomPortal) {
|
||||||
|
portalRoots.unshift(parent);
|
||||||
}
|
}
|
||||||
if (parent.tag === DomPortal) {
|
if (parent.tag === DomPortal) {
|
||||||
pushCurrentRoot(parent);
|
pushCurrentRoot(parent);
|
||||||
}
|
}
|
||||||
parent = parent.parent;
|
parent = parent.parent;
|
||||||
}
|
}
|
||||||
|
portalRoots.forEach(node => {
|
||||||
|
pushCurrentRoot(node);
|
||||||
|
});
|
||||||
contextProviders.forEach(node => {
|
contextProviders.forEach(node => {
|
||||||
setContext(node, node.props.value);
|
setContext(node, node.props.value);
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue