之前介绍了一波混入 mixin 和 自定义指令 directive 其基本作用就是为了在 vue 中实现代码的复用. 而本篇介绍的是 vue3 的一个新特性叫做传送门.
一听这个名字是不是就感觉特别科幻呢? 小时候看哆啦A梦的就经常使用传送门, 只要心里想着那个地方, 就能直接穿越过去. 然后就是在漫威宇宙中奇异博士的传送门啦, 想去哪就画个圈圈传送过去哦.
在 vue 中就表现为对一个 dom 进行有目的的直接传送啦, 这里我们以一个局部的蒙层来做演示:
<!DOCTYPE html>
<html lang="en">
<head>
<title>蒙层</title>
<script src="https://unpkg.com/vue@3"></script>
<style>
.box {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 300px;
background: skyblue;
}
.mask {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, .25);
}
</style>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
data () {
return {
show: false
}
},
methods: {
handleClick () {
this.show = !this.show
}
},
template: `
<div class="box">
<button @click="handleClick">点我变蒙层</button>
<div class="mask" v-show="show"></div>
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
可以发现在这个200 x 300px 的浅蓝色 box 中, 当我们点击 "点我变蒙层" 的按钮时, 只会作用于这个内部盒子而不会作用整个页面, 因为咱这个 mask 就是写在 box 中的嘛.
template: `
<div class="box">
<button @click="handleClick">点我变蒙层</button>
<div class="mask" v-show="show"></div>
</div>
`
而要实现整个页面的效果, 则咱需要将这个 mask 作用到 body 中去, 或者说将其直接"传送"到 body 下面哦.
传送门演示
来了老铁, 直接将这个 mask 传递到 body 哦, 即通过 teleport 这个标签来安排.
<!DOCTYPE html>
<html lang="en">
<head>
<title>传送门 teleport </title>
<script src="https://unpkg.com/vue@3"></script>
<style>
.box {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 200px;
height: 300px;
background: skyblue;
/* 让按钮的优先级增加以至于蒙层后不被覆盖掉 */
z-index: 2;
}
.mask {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: rgba(0, 0, 0, .25);
}
</style>
</head>
<body>
<div id="root"></div>
<script>
const app = Vue.createApp({
data () {
return {
show: false
}
},
methods: {
handleClick () {
this.show = !this.show
}
},
template: `
<div class="box">
<button @click="handleClick">点我变蒙层</button>
<teleport to="body">
<div class="mask" v-show="show"></div>
</teleport>
</div>
`
})
const vm = app.mount('#root')
</script>
</body>
</html>
其核心就是这里的 teleplort 标签的包裹和 to 这个传送到哪啦.
template: `
<div class="box">
<button @click="handleClick">点我变蒙层</button>
<teleport to="body">
<div class="mask" v-show="show"></div>
</teleport>
</div>
`
当然也可以传送到比如模板中有一个 ID 为 youge 的标签中:
<teleport to="#youge">
<div class="mask" v-show="show"></div>
</teleport>
当然除了传蒙层, 对于其他的一些场景如 tab 块呀, 组件呀, dom 内容呀, 都是可以通过 teleport 进行传送的, 与我而言, 其好奇的科幻程度远大于应用程度啦. 那关于传送门的基本认知就先到这里啦.
小结
- 传送门就是将某个 dom 或组件等能够传递到该模板的任意位置中, 类似奇异博士的传送门
- 实现上就在 dom / 组件 外包裹一层 teleport 标签, to="选送的位置, 选择器" 即可
- 好奇和科幻的程度远大于对它的实际应用程度啦