uni-app 5.14 Compiles Vue <teleport> Directly to Mini Program <root-portal>
Foreword
When writing components like modals, drawers, toasts, and action sheets in Vue, teleport is a very common capability. It can render content outside the current component hierarchy, preventing it from being affected by parent overflow, z-index, or style isolation.
But mini programs are not browsers; they don't have a real document.body, and you can't move DOM nodes around freely like on the Web. So previously, when building cross-platform components, you often had to write code like this:
<!-- #ifdef H5 -->
<teleport to="body">
<popup />
</teleport>
<!-- #endif -->
<!-- #ifdef MP-WEIXIN -->
<root-portal>
<popup />
</root-portal>
<!-- #endif -->
Starting from version 5.14, mini program platforms support writing teleport directly. Developers no longer need to write two sets of conditional compilation for H5 and mini programs; they can use Vue's unified syntax.
<teleport to="body">
<popup />
</teleport>
On the H5 side, it remains Vue's native teleport; on supported mini program platforms, uni-app automatically converts it into the platform's native root-portal.
Supported Platforms
Currently supported platforms are:
- WeChat Mini Program
- Alipay Mini Program
- JD Mini Program
Usage
Usage is consistent with Vue:
<template>
<view class="page">
<button @click="show = true">Open Modal</button>
<teleport to="body">
<view v-if="show" class="mask" @click="show = false">
<view class="dialog" @click.stop>
I am the modal content
</view>
</view>
</teleport>
</view>
</template>
<script setup>
import { ref } from 'vue'
const show = ref(false)
</script>
After compiling to a supported mini program platform, the template will become something like this:
<root-portal>
<view class="mask">
<view class="dialog">
I am the modal content
</view>
</view>
</root-portal>
In other words, the developer writes teleport, but what the mini program actually runs is root-portal.
Implementation Principle
This support is essentially a compile-time transformation.
During the mini program compilation phase, uni-app identifies the teleport tag in the template and converts it into root-portal. This preserves the Vue development experience while leveraging the existing native capabilities of the mini program platform.
Overall, it can be understood as:
<teleport to="body">
<view />
</teleport>
Compiled to:
<root-portal>
<view />
</root-portal>
It's important to note that the mini program's root-portal and Vue's teleport are not fully equivalent capabilities. Vue's teleport can specify a target node via to, whereas the mini program's root-portal elevates content to render under the page's root node and does not support teleporting to arbitrary positions.
So what uni-app does is capability mapping, not a complete simulation of Web Teleport within the mini program.
Attribute Differences
Although the usage is unified as teleport, the mini program side ultimately falls back to root-portal, so some attributes will differ.
to and defer
to and defer are both Vue Teleport attributes, but the mini program's root-portal has no corresponding capability, so they are removed when compiled to the mini program side.
<teleport to="body" defer>
<popup />
</teleport>
Will be converted to something like:
<root-portal>
<popup />
</root-portal>
If the code runs on both H5 and mini programs, you can keep these attributes: to="body" and defer still have meaning on the H5 side, they just won't take effect on the mini program side.
disabled
Vue Teleport uses disabled to control whether teleportation is disabled:
<teleport :disabled="disabled">
<popup />
</teleport>
The mini program's root-portal uses enable, which has the opposite semantics. Therefore, when compiling to the mini program, uni-app automatically performs a negation conversion.
For example:
<teleport :disabled="disabled">
<popup />
</teleport>
Will be processed into something like:
<root-portal :enable="!disabled">
<popup />
</root-portal>
Developers can still write code according to Vue's disabled semantics without manually changing it to enable.
Top 2 from juejin.cn, machine-translated. The original thread is authoritative.
uni-app is getting stronger and stronger 👏
[Like]