Teleport组件介绍

Vue3新增组件,该组件可以将制定内容渲染到制定容器中。默认内容都是渲染到元素app内,我们可以将其渲染到任意节点 (传送门)

const shapeFlag = isString(type)  
        ? ShapeFlags.ELEMENT: isTeleport(type) // 如果是穿梭框
        ? ShapeFlags.TELEPORT: isObject(type)
        ? ShapeFlags.STATEFUL_COMPONENT :isFunction(type) 
        ? ShapeFlags.FUNCTIONAL_COMPONENT:0; // 函数式组件
1
2
3
4
5

创建虚拟节点的时候标识组件类型。

组件挂载

if(shapeFlag & ShapeFlags.TELEPORT){
    type.process(n1,n2,container,anchor,{
        mountChildren, // 挂载孩子
        patchChildren, // 更新孩子
        move(vnode,container){ // 移动元素
            hostInsert(vnode.component? vnode.component.subTree.el : vnode.el,container)
        }
    })
}
1
2
3
4
5
6
7
8
9
export const TeleportImpl = {
    __isTeleport:true,
    process(n1,n2,container,anchor,internals){
        let {mountChildren,patchChildren,move} = internals
        if(!n1){
            // 创建一个目标
            const target = (n2.target = document.querySelector(n2.props.to));
            if(target){
                mountChildren(n2.children,target,anchor)
            }
        }else{
            patchChildren(n1,n2,container); // 比对儿子
            if(n2.props.to !== n1.props.to){  // 更新并且移动位置
                // 获取下一个元素
                const nextTarget = document.querySelector(n2.props.to);
                n2.children.forEach(child =>move(child,nextTarget));
            }
        }
    }
}
export const isTeleport = (type) => type.__isTeleport
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21