vue3 teleport 类似 Portal 转移dom和组件

原创
09/13 20:11
阅读数 292

https://juejin.im/post/6868260498417123335

和react 的portal一样, 将组件挂载到指定的位置

传入的字符串为作为选择器, 所以尽量使用比较精确的选择器

teleport 有属性disable, 表示是否转移dom

如果转移的dom有css, 注意转移后的层级会变化, 所以会影响css

不仅可以转移dom, 也能够转移组件, 此时最好使用css-scoped

 

demo 效果, 将组件内的dom, 转移到组件外部

 

 

创建项目

npm i @vue/cli -g

vue add vue-next

vue create vue3-cli-demo

虽然报错了, 但是插件可以使用

 

 

vue的版本有点低的感觉

 

yarn add vue@rc

 

@vue/compiler-sfc

 

修改hello组件

 

dom的层级已经发生了变化

 

调整后的层级对css的影响

<template>
  <div class="hello">
    <teleport to="body">
      <img name="img1" src="../assets/logo.png" alt="" />
    </teleport>
    <img name="img1" src="../assets/logo.png" alt="" />
  </div>
</template>

<script>
export default {
};
</script>

<style>
body img {
  background: black;
}

.hello img {
  width: 100px;
  background: blue;
}
</style>

 

 

 

 

app.vue

<template>
  <HelloWorld />
  <div class="rect top"></div>
  <div class="rect bottom"></div>
  <div class="rect left"></div>
  <div class="rect right"></div>
</template>

<script>
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld,
  },
};
</script>

<style>
html,
body {
  padding: 0;
  margin: 0;
  width: 100vw;
  height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.rect {
  width: 200px;
  height: 200px;
  border: 1px solid black;
  position: absolute;
}

.rect.left {
  left: 0;
  top: 30%;
}
.rect.top {
  left: 0;
  top: 0%;
  left: 50%;
}
.rect.right {
  top: 30%;
  right: 0;
}
.rect.bottom {
  left: 0;
  left: 50%;
  bottom: 0;
}

.rect .img {
  background: chartreuse;
}
</style>

 

hello.vue

<template>
  <div class="hello">
    <teleport :to="target" :disabled="disabeled">
      <img class="img" name="img1" src="../assets/logo.png" alt="" />
    </teleport>
    <div>
      <button @click="move('top')">top</button>
      <button @click="move('bottom')">bottom</button>
      <button @click="move('left')">left</button>
      <button @click="move('right')">right</button>
      <button @click="move()">disabele</button>
    </div>
  </div>
</template>

<script>
import { ref } from "vue";
export default {
  setup() {
    const disabeled = ref(true);
    const target = ref(".hello");
    const move = (to) => {
      console.log("move", to);
      if (!to) {
        disabeled.value = true;
      } else if (to === "top") {
        disabeled.value = false;
        target.value = ".rect.top";
      } else if (to === "left") {
        disabeled.value = false;
        target.value = ".rect.left";
      } else if (to === "right") {
        disabeled.value = false;
        target.value = ".rect.right";
      }else if (to === "bottom") {
        disabeled.value = false;
        target.value = ".rect.bottom";
      }
    };
    return {
      disabeled,
      move,
      target,
    };
  },
};
</script>

<style>
.hello .img {
  width: 100px;
  background: blue;
}
</style>

 

展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部