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 是组件声明),但它们解决了完全相同的问题,并且设计理念也高度一致。如果你熟悉其中一个,理解另一个将毫无障碍。

相关推荐
林晓lx20 分钟前
使用Git钩子+ husky + lint语法检查提高前端项目代码质量
前端·git·gitlab·源代码管理
王同学要变强1 小时前
【深入学习Vue丨第二篇】构建动态Web应用的基础
前端·vue.js·学习
程序定小飞1 小时前
基于springboot的web的音乐网站开发与设计
java·前端·数据库·vue.js·spring boot·后端·spring
Hello_WOAIAI1 小时前
2.4 python装饰器在 Web 框架和测试中的实战应用
开发语言·前端·python
FinClip1 小时前
凡泰极客亮相香港金融科技周,AI助力全球企业构建超级应用
前端
阿四1 小时前
【Nextjs】为什么server action中在try/catch内写redirect操作会跳转失败?
前端·next.js
申阳1 小时前
Day 6:04. 基于Nuxt开发博客项目-LOGO生成以及ICON图标引入
前端·后端·程序员
中国lanwp2 小时前
npm中@your-company:registry 和 registry 的区别
前端·npm·node.js
Bacon2 小时前
Electron 应用商店:开箱即用工具集成方案
前端·github
行走的陀螺仪2 小时前
uni-app + Vue3 实现折叠文本(超出省略 + 展开收起)
前端·javascript·css·uni-app·vue3