vue3 Teleport 传送门

先放个官方文档链接~

某位同事研究vue3时,发现vue3的Teleport使用起来有点问题。

<template>
  <div class="test">1
    <div class="qwe">2</div> 
    <teleport to=".qwe">333</teleport>    //情况一:失败并报错
  </div>
<teleport to=".qwe">333</teleport>   //情况二:成功传送
</template>

去官方文档看了一下,有如下提示

也就是说,元素最好要挂载到#app的外面,原理其实是解析到teleport的时候,需要能获取到to指向的dom元素。

自己试了一下,发现确实如此,听官方的话,不行就加个v-if吗,等mounted之后再获取,so easy~(

但是为了了解原理,我还是启了个vue3项目,结果发现在不考虑v-if的情况下,情况一和情况二都失败了。

自己测试了一下,也打断点看了看源码(代码里直接搜resolveTarget方法),最终得出了结论。

网页版和项目版的区别,就在于teleport标签的位置是不是vue根标签#app的子标签,项目版的文件嵌套了路由,所以就有好几层。

源码原理:vue由虚拟dom解析到真实dom,确实是由上而下进行的。但是根标签#app是一直存在的(真要删也不是不行),所以尤雨西才推荐我们把to指向#app外面的标签,比如它爸爸body标签,这样可以保证无论vue应用怎么变化,teleport的to都能获取到对应的标签,然后传送过去。

以下两个例子就能解释明白了:

// 一、 App.vue  在根应用下
// 这时,Vue是从上到下解析并渲染的,先#test,再Teleport标签,再.test1。所以执行到Teleport标签时,就能获取到.text标签了。 <template> <div id="test"> <p>我是test</p > <div class="text"> <div class="teleport"> <p>我是teleport</p > </div> </div> <Teleport to=".text"> <h3>嗨,我是teleport的兄弟</h3> </Teleport> <div class="test1">7777</div> </div> </template>
// 二、 App.vue ,但不在根应用下
// 这时,vue解析是先看#app底下的#aaa,发现只有一个标签,就进入并解析其所有子标签,待所有子标签解析完成,才会对整个#aaa进行渲染。
// 所以,是先解析#test、.text、<Teleport>,但是并没有进行渲染,这时候在resolveTarget打断点,会发现element里只有一个孤零零的#app,里面啥都没
// 所以解析到Teleport的时候,获取不到to属性对应的标签,就报错并且失败了 <template> <div id="#aaa"> <div id="test"> <p>我是test</p > <div class="text"> <div class="teleport"> <p>我是teleport</p > </div> </div> <Teleport to=".text"> <h3>嗨,我是teleport的兄弟</h3> </Teleport> <div>7777</div> </div> </div> </template>

  

posted @ 2022-08-30 14:44  太阳锅锅  阅读(485)  评论(1编辑  收藏  举报