美文网首页Vue
Vue3 新特性 —— teleport 瞬间移动

Vue3 新特性 —— teleport 瞬间移动

作者: Lia代码猪崽 | 来源:发表于2021-01-13 15:01 被阅读0次

官方文档

Teleport | Vue3中文文档

视频教程

teleport | Vue School 的免费课程

似曾相识?
没错就是它!

详细的 teleport 使用步骤

1. 定义要瞬移的内容

使用 <teleport></teleport> 标签包裹内容,且给 to 属性绑定瞬移位置的选择器。

/src/components/HelloWorld.vue

<template>
  <div class="hello">
    <div>Hello World</div>
    <teleport to="#modal">
      <h1>Hello Modal</h1>
    </teleport>
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";

export default defineComponent({
  name: "HelloWorld",
  props: {
    msg: String
  }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
  margin: 40px 0 0;
  color: #42b983;
}
</style>

2. 引入 HelloWorld 组件,且设定要瞬移后的位置

/src/App.vue

<template>
  <div id="app">
    <h1>{{ count }}</h1>
    <button @click="plus">plus</button>
    <br />
    <HelloWorld />
    <div
      id="modal"
      style="border: 1px solid #42b983; padding: 20px; margin: 20px 0"
    ></div>
  </div>
</template>

<script lang="ts">
import { ref } from "vue";
import HelloWorld from "./components/HelloWorld.vue";

export default {
  name: "App",
  components: {
    HelloWorld
  },
  setup() {
    const count = ref(0);
    function plus() {
      count.value++;
    }

    return {
      count,
      plus
    };
  }
};
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

3. 这时候可以看到控制台有warning

建议将要瞬移后的位置移动到整个 vue 组件树的外面

4. 将瞬移后的位置改为在 index.html 里

/public/index.html

<!DOCTYPE html>
<html lang="">
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width,initial-scale=1.0" />
    <link rel="icon" href="<%= BASE_URL %>favicon.ico" />
    <title><%= htmlWebpackPlugin.options.title %></title>
  </head>
  <body>
    <noscript>
      <strong
        >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
        properly without JavaScript enabled. Please enable it to
        continue.</strong
      >
    </noscript>
    <div id="app"></div>
    <!-- #modal 放在 #app 后 -->
    <div
      id="modal"
      style="border: 1px solid #42b983; padding: 20px; margin: 20px 0"
    ></div>
    <!-- built files will be auto injected -->
  </body>
</html>

5. 能正常显示了

6. 加入数据交互

假设就为一个 Modal

  • 默认为不渲染状态。
  • HelloWorld 组件里有一个按钮,点击能渲染显示 Modal
  • Modal 内部有一个按钮,点击能关闭 Modal
<template>
  <div class="hello">
    <div>Hello World</div>
    <!-- 在 HelloWorld 组件里有一个按钮,点击能渲染显示 Modal -->
    <button @click="showModal = true">open modal</button>
    <teleport to="#modal">
      <!-- showModal 状态来控制是否显示 Modal 内容 -->
      <template v-if="showModal">
        <h1>Hello Modal</h1>
        <!-- Modal 内部有一个按钮,点击能关闭 Modal -->
        <button @click="showModal = false">close</button>
      </template>
    </teleport>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  name: "HelloWorld",
  props: {
    msg: String
  },
  setup() {
    // showModal 状态来控制是否显示 Modal 内容
    const showModal = ref(false);

    return {
      showModal
    };
  }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
  margin: 40px 0 0;
  color: #42b983;
}
</style>
完美

可以观察到:

虽然我们是在 HelloWorld.vue 组件里定义 <teleport to="#modal"></teleport> 内容的,但它实际渲染的位置在 #modal 处,完成了“瞬间移动”。

teleport 上还有一个属性 disabled

设置为 true

<template>
  <div class="hello">
    <div>Hello World</div>
    <!-- 在 HelloWorld 组件里有一个按钮,点击能渲染显示 Modal -->
    <button @click="showModal = true">open modal</button>
    <teleport to="#modal" :disabled="true">
      <!-- showModal 状态来控制是否显示 Modal 内容 -->
      <template v-if="showModal">
        <h1>Hello Modal</h1>
        <!-- Modal 内部有一个按钮,点击能关闭 Modal -->
        <button @click="showModal = false">close</button>
      </template>
    </teleport>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from "vue";

export default defineComponent({
  name: "HelloWorld",
  props: {
    msg: String
  },
  setup() {
    // showModal 状态来控制是否显示 Modal 内容
    const showModal = ref(false);

    return {
      showModal
    };
  }
});
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.hello {
  margin: 40px 0 0;
  color: #42b983;
}
</style>

查看页面会发现:弹窗内容不在 #modal 即绿色框里

查看 DOM 结构:


渲染在 HelloWorld.vue 组件里了

相关文章

网友评论

    本文标题:Vue3 新特性 —— teleport 瞬间移动

    本文链接:https://www.haomeiwen.com/subject/jbvuaktx.html