text
existDOM
In components with relatively complex structure and deep hierarchy nesting, some logic needs to be processed according to the corresponding module business, which belongs to the current component.
But from the view of the entire page application, itDOM
It should be rendered throughoutvue
Other places outside the application cannot affect the structure of the component
A more common application scenario: a full-screen modal box that controls the position of elements, which can also be handled, but it is more troublesome
Ideally, we want to bind the event to the element in a specific component, and the specific to control the event to be controlled.DOM
The element structure maintains a certain correlation at the specific location in the same component
Without having to put someDOM
The structure is separated, however, in the same component, the button that triggers the modal box and the modal box themselves are in the same component
Because they are all associated with the switch state of the component, the modal box and the button are rendered together in the applicationDOM
Where the structure is very deep, it will make it very difficult to control the CSS layout position of the modal box
Given such scenarios and difficulties,Vue
Officially provided aTeleport
Components can solve this problem very well, so that developers don't need to worry about itDOM
Structural issues
01-Component Set When the Component Hierarchy is very deep
For example: There are now two components, parent component and child component. In the descendant component, add a button and a modal box pops up, making it appear vertically and horizontally centered on the page.
As shown below, the parent component is as shown below
<template> <div class="App"> I'm the parent component <Child /> </div> </template> <script setup> import Child from "./" </script> <style> .App { width: 400px; height: 400px; background:red; } </style>
The following isChild
Component, sample code is as follows,We need to add a button in the grandson (descendant) component, click the button, and a pop-up box will pop up, and it will be displayed horizontally and vertically in the center of the page.
<template> <div class="child"> <p>I'm a child component</p> <button @click="isModel=true">Open the modal box</button> <div class="mask-dialog" v-if="isModel"> <div class="box"> <h2>I'm the title</h2> <div>I'm pop-up content</div> <div> <button @click="isModel=false">closure</button> </div> </div> </div> </div> </template> <script setup> import { ref } from "vue"; let isModel = ref(false); </script> <style> .child { width: 300px; height:300px; background:green; } /**Gray mask layer */ .mask-dialog { width: 100%; height:100%; position:absolute; left:0; top:0; background:rgba(0,0,0,0.5) } .box { width: 200px; height:200px; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); background:pink; text-align:center; } </style>
There is one in the above subcomponentbutton
The button triggers the modal box to open the current component, which contains the logic to control the display and hidden of the pop-up box. When the nested components are deep and complex
If the parent element has positioning, then when controlling the position of the child element, usecss
oftransform
orposition:absolute
,Reference object changes will destroy the layout structure and somecss
style
The problem of control will be very painful to solve.
Then thisTeleport
Components are designed to solve this problem.DOM
Structural fragments are independent of going outside the component and are not affected by the current component layout structure.
go throughTeleport
After modification
<template> <div class="child"> <p>I'm a child component</p> <button @click="isModel=true">Open the modal box</button> <Teleport to="body"> <div class="mask-dialog" v-if="isModel"> <div class="box"> <h2>I'm the title1</h2> <div>I'm pop-up content</div> <div> <button @click="isModel=false">closure</button> </div> </div> </div> </Teleport> </div> </template> <script setup> import { ref } from "vue"; let isModel = ref(false); </script> <style> .child { width: 300px; height:300px; background:green; } /**Gray mask layer */ .mask-dialog { width: 100%; height:100%; position:absolute; left:0; top:0; background:rgba(0,0,0,0.5) } .box { width: 200px; height:200px; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); background:pink; text-align:center; } </style>
<Teleport>
Receive oneto prop
To specify the destination of the transmission.to
The value of can be aCSS
selector string, orid
, it can also be oneDOM
Element object. The purpose of this code is to tellVue
Transfer the following template fragment tobody
Under the tag
<Teleport to="#some-id">html structure code</Teleport><Teleport to=".some-class">htmlStructure code</Teleport> <Teleport to="body">htmlStructure code</Teleport> <Teleport to="html">htmlStructure code</Teleport>
02-Teleport component
It isVue
An official built-in component that can "transmit" a part of the template inside a component to the component'sDOM
The location of the outer layer of the structure is a kind of component that can bring ourhtml
Technology of moving structures to specified locations
<teleport to="Move to the specified location, which can be html, body, or id, class"> It's insideHtmlStructural template content </teleport>
Notice
<Teleport>
When mounted, transmittedto
The goal must already exist inDOM
middle. Ideally, this should be the wholeVue
ApplicationDOM
An element outside the tree. If the target element is alsoVue
Rendered, you need to make sure it is mounted<Teleport>
The element was mounted first
thisteleport
The specified template ishtml
, placed at the specified position in the page. It is conditional and cannot be transmitted at will.
Before installing a component, the target element must exist, i.e., the target cannot be presented by the component itself, and should ideally be located in the entireVue
Outside the component tree.
The following code is not OK
<template> <div class="header"> <Teleport to=".content"> <div>I'm the content of the head</div> </Teleport> </div> <div class="footer"> Bottom content <div class="content"></div> </div> </template> <script setup> </script> <style lang="less"> h1 { color: red; } </style>
03-What you need to know
teleport
It just changed the renderingDOM
Structure, it will not affect the logical relationship between components. That is, if<Teleport>
Contains a component, then the component is always used with this<teleport>
The components of maintain a logical parent-son relationship. Incomingprops
and triggered events will also work as usual.
This also means that injection from the parent component will work as expected, and the child component will be inVue Devtools
Nested under the parent component, not where the actual content is moved to
The position has moved and is brought to the structural template, but the data logic is still related
04-How to disable Teleport
In some scenarios, it may need to be disabled as appropriate.<Teleport>
. For example, we want to render a component as a floating layer on the desktop, but on the mobile side as an inline component. We can pass <Teleport>
Dynamically pass in onedisabled prop
To deal with these two different situations
<Teleport :disabled="isMobile"> ... </Teleport>
HereisMobile
The status can be based on CSS media query
Different results of are updated dynamically
05-When multiple Teleports share targets
A reusable modal box component may have multiple instances at the same time. For such scenarios, multiple<Teleport>
The component can mount its content on the same target element, and the order is simply appended in sequence, and the subsequent mounted will be placed at a later position under the target element.
For example, the following use case
<Teleport to=".content"> <div>A</div> </Teleport> <Teleport to=".content"> <div>B</div> </Teleport>
The rendering result is
<div class="content"> <div>A</div> <div>B</div> </div>
Summarize
thisteleport
Components are still very practical in actual development, and can solve the problem that when the component nesting level is very deep, the templates in later components want to be separated from the current component structure.css
Disturbance at the layout level, then you can use thisteleport
Components
The above is a detailed explanation of how to use Teleport and component nesting hierarchy in VueJs. For more information about VueJs using Teleport components, please pay attention to my other related articles!