vue3 teleport 类似 Portal 转移dom和组件

原文链接: vue3 teleport 类似 Portal 转移dom和组件

上一篇: 本子里的数学题....

下一篇: react 高阶组件 HOC

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

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

up-6843b6b59f16ba27f10e2c42cfb9e170ffa.png

up-08d006344ff985faa7dfc2b72c252f18ba2.png

up-f74a305bcea111427a57c48ea599a484892.png

vue的版本有点低的感觉

up-74f0084dd29d67ff13a7192cb5d6b905f28.png

yarn add vue@rc

up-1b0297c5bc03a6f803f3437195ac78dcd13.png

@vue/compiler-sfc

up-f1d6e3b8bab492f9da11e60fadf57248b73.png

修改hello组件

up-a46d432a2e5647d97bc31af1b671431aadb.png

dom的层级已经发生了变化

up-99400d938345c47da68dd3ac571124169dd.png

调整后的层级对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>

up-07e70d818892f14fe734770d3a3cf0ef16d.png

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
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值