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

相关推荐
. . . . .1 小时前
shadcn组件库
前端
2501_944711432 小时前
JS 对象遍历全解析
开发语言·前端·javascript
发现一只大呆瓜2 小时前
虚拟列表:支持“向上加载”的历史消息(Vue 3 & React 双版本)
前端·javascript·面试
css趣多多2 小时前
ctx 上下文对象控制新增 / 编辑表单显示隐藏的逻辑
前端
lbb 小魔仙2 小时前
【HarmonyOS实战】React Native 表单实战:自定义 useReactHookForm 高性能验证
javascript·react native·react.js
_codemonster2 小时前
Vue的三种使用方式对比
前端·javascript·vue.js
寻找奶酪的mouse2 小时前
30岁技术人对职业和生活的思考
前端·后端·年终总结
梦想很大很大3 小时前
使用 Go + Gin + Fx 构建工程化后端服务模板(gin-app 实践)
前端·后端·go
We་ct3 小时前
LeetCode 56. 合并区间:区间重叠问题的核心解法与代码解析
前端·算法·leetcode·typescript
张3蜂3 小时前
深入理解 Python 的 frozenset:为什么要有“不可变集合”?
前端·python·spring