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

相关推荐
程序员小寒7 分钟前
前端高频面试题之CSS篇(一)
前端·css·面试·css3
颜酱23 分钟前
Monorepo 架构以及工具选型、搭建
前端·javascript·node.js
oden27 分钟前
ChatGPT不推荐你?7个GEO技巧让AI主动引用你的内容
前端
李游Leo1 小时前
前端安全攻防指南:XSS / CSRF / 点击劫持与常见防护实践(含真实案例拆解)
前端·安全·xss
我命由我123452 小时前
微信开发者工具 - 模拟器分离窗口与关闭分离窗口
前端·javascript·学习·微信小程序·前端框架·html·js
E***q5392 小时前
Vue增强现实开发
前端·vue.js·ar
S***42802 小时前
JavaScript在Web中的Angular
前端·javascript·angular.js
黑幕困兽2 小时前
ehcarts 实现 饼图扇区间隙+透明外描边
前端·echarts
San302 小时前
深入理解 JavaScript 词法作用域链:从代码到底层实现机制
前端·javascript·ecmascript 6
七淮2 小时前
Next.js SEO 优化完整方案
前端·next.js