react【portals】与vue3【<Teleport>】

它们都是为了解决同一个问题:将组件的子节点渲染到存在于父组件 DOM 层次结构之外的 DOM 节点中。

核心概念对比

特性 React Vue 3
功能 将子节点渲染到父组件 DOM 结构之外 将其包裹的内容移动到应用 DOM 结构中的指定位置
API ReactDOM.createPortal(children, domNode) <Teleport> 组件 + to 属性
代码位置 通常在 render() 方法或组件返回值中使用 作为模板中的标签使用

举例:

公共 HTML 结构 (index.html)

html 复制代码
<body>
  <div id="root"></div> <!-- React 应用挂载点 -->
  <div id="app"></div> <!-- Vue 应用挂载点 -->
  <!-- 模态框将要被渲染到这个节点 -->
  <div id="modal-root"></div>
</body>

1. React 实现:使用 Portals

jsx 复制代码
// Modal.jsx
import React, { PureComponent } from 'react'
import { createPortal } from "react-dom"

export class Modal extends PureComponent {
  render() {
    return createPortal(this.props.children,   document.getElementById('modal-root') ))
  }
}
jsx 复制代码
// App.jsx
import React, { PureComponent } from 'react'
import { createPortal } from "react-dom"
import Modal from './Modal'

export class App extends PureComponent {
  render() {
    return (
      <div className='app'>
        <h1>App H1</h1>
        {
          createPortal(<h2>App H2</h2>, document.querySelector("#why"))
        }

        {/* 2.Modal组件 */}
        <Modal>
          <h2>我是标题</h2>
          <p>我是内容, 哈哈哈</p>
        </Modal>
      </div>
    )
  }
}

export default App

2. Vue 3 实现:使用 <Teleport>

vue 复制代码
<!-- Modal.vue -->
<template>
  <Teleport to="#modal-root" v-if="isOpen">
    <div class="modal-overlay" @click="$emit('close')">
      <div class="modal-content" @click.stop>
        <button @click="$emit('close')">关闭</button>
        <slot></slot>
      </div>
    </div>
  </Teleport>
</template>

<script setup>
defineProps(['isOpen']);
defineEmits(['close']);
</script>
vue 复制代码
<!-- App.vue -->
<template>
  <div class="app">
    <h1>我的 Vue 应用</h1>
    <button @click="isModalOpen = true">打开模态框</button>
    <!-- 即使 Modal 在这里被使用,它的 HTML 将被 Teleport 到 #modal-root -->
    <Modal :is-open="isModalOpen" @close="isModalOpen = false">
      <p>这是从 Vue Teleport 渲染的内容!</p>
    </Modal>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import Modal from './components/Modal.vue';

const isModalOpen = ref(false);
</script>

关键区别与共同点

共同点:

  1. 逻辑位置不变 :在 React 的虚拟 DOM 树或 Vue 的组件树中,Modal 组件仍然位于 App 组件的子节点位置。这意味着它仍然能继承父组件的上下文(React Context / Vue Provide/Inject),事件冒泡在虚拟树中也会正常发生。
  2. DOM 位置改变 :最终生成的 HTML 结构被移动到了指定的目标容器(如 #modal-root)中。

区别:

方面 React Portal Vue 3 <Teleport>
语法 是一个函数 ReactDOM.createPortal() 是一个内置组件 <Teleport>
条件渲染 通常在 Portal 外部使用 if (!isOpen) return null; 可以在 <Teleport> 标签上使用 v-ifv-show
目标指定 通过函数第二个参数(DOM 节点)指定 通过 to 属性(CSS 选择器字符串)指定
组合性 更偏向函数式,可在逻辑中动态创建 更偏向声明式,作为模板的一部分

总结

React Portals 等于 Vue 3 的 <Teleport> 组件。

它们都是用于"传送"DOM结构的解决方案。虽然语法和实现方式不同(React 是函数调用,Vue 是组件声明),但它们解决了完全相同的问题,并且设计理念也高度一致。如果你熟悉其中一个,理解另一个将毫无障碍。

相关推荐
用户69371750013843 小时前
Google 正在“收紧侧加载”:陌生 APK 安装或需等待 24 小时
android·前端
蓝帆傲亦3 小时前
Web 前端搜索文字高亮实现方法汇总
前端
用户69371750013843 小时前
Room 3.0:这次不是升级,是重来
android·前端·google
漫随流水4 小时前
旅游推荐系统(view.py)
前端·数据库·python·旅游
踩着两条虫5 小时前
VTJ.PRO 核心架构全公开!从设计稿到代码,揭秘AI智能体如何“听懂人话”
前端·vue.js·ai编程
jzlhll1236 小时前
kotlin Flow first() last()总结
开发语言·前端·kotlin
蓝冰凌7 小时前
Vue 3 中 defineExpose 的行为【defineExpose暴露ref变量】详解:自动解包、响应性与实际使用
前端·javascript·vue.js
奔跑的呱呱牛7 小时前
generate-route-vue基于文件系统的 Vue Router 动态路由生成工具
前端·javascript·vue.js
柳杉8 小时前
从动漫水面到赛博飞船:这位开发者的Three.js作品太惊艳了
前端·javascript·数据可视化