Teleport
基本用法
Teleport
提供了一种方法,允许我们控制在 DOM
中哪个父节点下渲染 HTML
。
默认情况下
<body>
<div id="app">
<my-component></my-component>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp } = Vue;
const Root = {};
const app = createApp(Root);
app.component("my-component", {
name: "my-component",
template: `
<div>
my-component
</div>
`,
});
app.mount("#app");
</script>
</body>
可以看到默认情况下组件被嵌套在 div
中。
渲染到指定的父节点下
<body>
<div id="app">
<my-component></my-component>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp } = Vue;
const Root = {};
const app = createApp(Root);
app.component("my-component", {
name: "my-component",
template: `
<teleport to="body">
<div>
my-component
</div>
</teleport>
`,
});
app.mount("#app");
</script>
</body>
现在,通过 Teleport
使组件渲染为 body
标签的子节点。
与 Vue components 一起使用
未使用 Teleport 情况下
<body>
<div id="app">
<parent-component></parent-component>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp } = Vue;
const Root = {};
const app = createApp(Root);
app.component("parent-component", {
name: "parent-component",
template: `
<div>
<p>parent-component</p>
<child-component></child-component>
</div>
`,
});
app.component("child-component", {
name: "child-component",
template: `
<div>
<p>child-component</p>
</div>
`,
});
app.mount("#app");
</script>
</body>
在未使用 Teleport
情况下,子组件嵌套在父组件中。
使用 Teleport 情况下
<body>
<div id="app">
<parent-component></parent-component>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp } = Vue;
const Root = {};
const app = createApp(Root);
app.component("parent-component", {
name: "parent-component",
template: `
<div>
<p>parent-component</p>
<teleport to="#app">
<child-component></child-component>
</teleport>
</div>
`,
});
app.component("child-component", {
name: "child-component",
template: `
<div>
<p>child-component</p>
</div>
`,
});
app.mount("#app");
</script>
</body>
可以看到,我们使用 Teleport
,通过 to
属性,指定子组件渲染的位置与父组件同级 。
在这种情况下,即使在不同的地方渲染子组件,但它仍是父组件的子级,并将从中接收 age
。
<body>
<div id="app">
<parent-component></parent-component>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp } = Vue;
const Root = {};
const app = createApp(Root);
app.component("parent-component", {
name: "parent-component",
template: `
<div>
<p>parent-component</p>
<teleport to="#app">
<child-component age="18"></child-component>
</teleport>
</div>
`,
});
app.component("child-component", {
name: "child-component",
template: `
<div>
<p>child-component: {{ age }}</p>
</div>
`,
props: ["age"]
});
app.mount("#app");
</script>
</body>
在同一目标上使用多个 teleport
可以将多个 <teleport>
组件挂载到同一个目标元素。顺序是简单的追加---先来的先挂载。
<body>
<div id="app">
<div id="target"></div>
<teleport to="#target">
<div>A</div>
</teleport>
<teleport to="#target">
<div>B</div>
</teleport>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp } = Vue;
const Root = {};
const app = createApp(Root);
app.mount("#app");
</script>
</body>
但要注意一点:标签 <teleport>
属性 to
指向的 DOM 元素要先存在,不然 <teleport>
组件渲染不出来。
<body>
<div id="app">
<teleport to="#target">
<div>A</div>
</teleport>
<teleport to="#target">
<div>B</div>
</teleport>
<div id="target"></div>
</div>
<script src="https://unpkg.com/vue@next"></script>
<script>
const { createApp } = Vue;
const Root = {};
const app = createApp(Root);
app.mount("#app");
</script>
</body>
像这个例子,元素 <div id="target"></div>
在 <teleport>
之后渲染,导致无法找到目标,从而渲染失败。