vue3——teleport组件瞬移

1,293 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第三天,点击查看活动详情

1.jpg

前言:

以前我们要是组件嵌套太深,想要固定一个组件在某个位置就得使用定位解决

vue3提供的teleport组件标签就是解决这个问题的,我们可以使用这个标签指定组件或者组件中的某些内容出现的位置,即可以将我们的组件html结构移动到指定位置

要点:

  1. teleport是一个vue内置的组件标签,就和keep-alive一样
  2. 一般使用这个标签都是向body传递内容(多层弹窗的情况)
  3. 需要一个参数(props)为:to,参数值可以是任何的css选择器(类选择器、id选择器、属性选择器、标签选择器);但是最好不用标签选择器

注意的点:

  1. 如果要转移的组件的参数to里面的选择器对应多个元素,会被转移到最外面(最上面)的元素
  2. 多个要转移的组件可以转移到同一个元素,加载先后顺序和组件加载顺序一致

可能会报错的点:

报错信息:

Failed to locate Teleport target with selector ".fd-teleport". Note the target element must exist before the component is mounted - i.e. the target cannot be rendered by the component itself, and ideally should be outside of the entire Vue component tree. 

报错的可能原因以及错误例子:要转移到的元素必须要在要转移的内容之前加载

// 需要转移的组件
<template>
    <teleport to=".fd-teleport">
        <div>provide:{{person.name}}</div>
    </teleport>
</template>
<script>
    import {reactive} from 'vue'
    export default {
        name: 'teleport1',
        setup(){
            let person = reactive({
                name:'yfeng',
                age:18,
                zy:{
                    old:'学生'
                }
            })
            function clickBtn() {
                person.name = 'yfeng1'
            }
            return {
                person,clickBtn
            }
        }
    }
</script>
// 要转移到的组件
<template>
    <ccTeleport></ccTeleport>
    <div class="fd-teleport">
        这里是装被转移的组件的元素2
    </div>
</template>
<script>
import ccTeleport from "./teleport1.vue"
    export default {
        name: 'teleport1',
        components:{ccTeleport},
        setup(){
        }
    }
</script>

报错的可能原因以及错误例子:要转移的内容不能被要转移到的内容所包含

// 需要转移的组件
<template>
    <teleport to=".fd-teleport">
        <div>provide:{{person.name}}</div>
    </teleport>
</template>
<script>
    import {reactive} from 'vue'
    export default {
        name: 'teleport1',
        setup(){
            let person = reactive({
                name:'yfeng',
                age:18,
                zy:{
                    old:'学生'
                }
            })
            function clickBtn() {
                person.name = 'yfeng1'
            }
            return {
                person,clickBtn
            }
        }
    }
</script>
// 要转移到的组件
<template>
    <div class="fd-teleport">
        这里是装被转移的组件的元素2
        <ccTeleport></ccTeleport>
    </div>
</template>
<script>
import ccTeleport from "./teleport1.vue"
    export default {
        name: 'teleport1',
        components:{ccTeleport},
        setup(){
        }
    }
</script>

正确例子:

// 需要转移的组件
<template>
    <teleport to=".fd-teleport">
        <div>provide:{{person.name}}</div>
    </teleport>
</template>
<script>
    import {reactive} from 'vue'
    export default {
        name: 'teleport1',
        setup(){
            let person = reactive({
                name:'yfeng',
                age:18,
                zy:{
                    old:'学生'
                }
            })
            function clickBtn() {
                person.name = 'yfeng1'
            }
            return {
                person,clickBtn
            }
        }
    }
</script>
// 正确写法
<template>
    <div class="fd-teleport">
        这里是装被转移的组件的元素2
    </div>
    <ccTeleport></ccTeleport>
</template>
<script>
import ccTeleport from "./teleport1.vue"
    export default {
        name: 'teleport1',
        components:{ccTeleport},
        setup(){
        }
    }
</script>

总结:

要转移到的地方能够从外往里找到一个就即刻停止了,所以如果最外层能找到要转移到的元素,里面(后面)的要转移到的元素是可以包裹要转移的组件元素的;所以这个组件标签最终于的点就是能够正确的找到要转移到的目标元素

 

例子:这个例子就可以正常加载要移动的组件,因为在最外面找到了一个class为fd-teleport的元素,不会再往下找,所以就算在teleport_parent文件中要移动组件被class为fd-teleport的元素包裹也不会有问题

// app.vue
<template>
    <div class="fd-teleport">
        这里是装被转移的组件的元素1
    </div>
    <teleportParent></teleportParent>
</template>
<script>
import teleportParent from "./components/teleport_parent"


export default {
    name: 'App',
    components:{teleportParent},
    setup() {
        
    }
}
</script>
// teleport_parent.vue
<template>
    <div class="fd-teleport">
        这里是装被转移的组件的元素2
        <ccTeleport></ccTeleport>
    </div>
    <div class="fd-teleport">
        这里是装被转移的组件的元素3
    </div>
</template>


<script>
import ccTeleport from "./teleport1.vue"
    export default {
        name: 'teleport1',
        components:{ccTeleport},
        setup(){
        }
    }
</script>
// teleport1.vue
<template>
    <teleport to=".fd-teleport">
        <div>provide:{{person.name}}</div>
    </teleport>
</template>
<script>
    import {reactive} from 'vue'
    export default {
        name: 'teleport1',
        setup(){
            let person = reactive({
                name:'yfeng',
                age:18,
                zy:{
                    old:'学生'
                }
            })
            function clickBtn() {
                person.name = 'yfeng1'
            }
            return {
                person,clickBtn
            }
        }
    }
</script>