vue3、react组件数据传值对比分析——父组件传递子组件,子组件传递父组件(一)

简介: vue3、react组件数据传值对比分析——父组件传递子组件,子组件传递父组件

⭐前言

大家好,我是yma16,本文分享关于vue、react组件数据传值对比分析——父组件传递子组件,子组件传递父组件。

react渲染原理

React 是一个基于组件的 JavaScript 库,用于构建用户界面。React 的主要原理是将用户界面抽象为一组嵌套的组件,每个组件都拥有自己的状态和行为。当组件的状态发生改变时,React 会自动重新渲染组件,并将更新后的组件插入到 DOM 树中。

React 的渲染过程主要涉及以下几个步骤:

  1. 首先,React 会根据 JSX 语法解析出虚拟 DOM(Virtual DOM)对象树,该虚拟 DOM 对象树只是一个 JavaScript 对象,其中包含了组件的状态、属性和子节点等信息。
  2. 然后,React 通过比较新旧虚拟 DOM 对象树,找出需要更新的部分,只更新需要更新的部分,称之为 “DOM Diff”。
  3. 接着,React 调用 render 方法生成新的虚拟 DOM 对象树,并将其与旧的虚拟 DOM 对象树进行比较。
  4. 如果新旧虚拟 DOM 对象树相同,则不进行任何操作。
  5. 如果新旧虚拟 DOM 对象树不同,则根据差异进行更新,生成新的虚拟 DOM 对象树。
  6. 最后,React 将更新后的虚拟 DOM 对象树渲染到真实的 DOM 上,完成渲染过程。

React 的渲染过程主要基于虚拟 DOM 和差异化算法。通过虚拟 DOM 对象树的比较,React 能够高效地进行局部更新,提高了应用程序的性能和用户体验。

vue渲染原理

Vue的渲染原理可以大致分为以下几个步骤:

  1. 解析模板:Vue会将模板字符串解析成抽象语法树(AST),这个过程中会标记出模板中的所有指令、插值语法、事件等信息。这一步由模板编译器完成。
  2. 根据AST生成渲染函数:Vue会从抽象语法树中生成一个可执行的渲染函数(render function),这个函数可以接收一个参数——渲染上下文(render context),并返回一个VNode节点。
  3. 渲染函数执行:当组件需要重新渲染时,Vue会执行渲染函数,生成一个新的VNode节点树。
  4. Diff算法对比新旧VNode:Vue将上一步生成的新VNode节点树和上一次渲染的旧VNode节点树进行对比,通过Diff算法找出需要更新的节点。
  5. 生成补丁(patch):Diff算法找出需要更新的节点后,会生成一个补丁对象(patch),这个补丁对象描述了要对哪些节点进行何种修改操作。
  6. 将补丁应用到真实的DOM上:最后,Vue将生成的补丁对象应用到真实的DOM节点上,完成组件的更新。

注:以上是Vue2.x版本的渲染原理,Vue3.x版本的渲染原理有所不同,主要是采用了基于Proxy的响应式数据自动更新机制以及模板编译器与运行时渲染器分离等新特性。

⭐react 组件传值实例

项目截图

💖父组件传值给子组件(props)

App.tsx通过标签内属性传递editInstance给EmailPage.tsx

父组件 App.txs

传递一个grapesjs实例到EmailPage

import './App.css';
import 'grapesjs/dist/css/grapes.min.css';
import grapesjs from 'grapesjs';
function App() {
  return (
      <div className="App">
        <EmailPage editInstance={grapesjs} ></EmailPage>
      </div>
  );
}
export default App;

子组件 EmailPage.tsx 解构props

解构接收props的editorInstance

import grapesJSMJML  from '../components/email-edit/index'
import { forwardRef, useEffect, useState,useImperativeHandle } from 'react'
const EmailPage=(props:any)=>{
    const [editor,setEditor]=useState();
    useEffect(()=>{
        const editorInstance:any = props.editInstance
            .init({
                fromElement: true,
                container: '#gjs-email',
                plugins: [grapesJSMJML ],
            });
        try{
            editorInstance.Commands.run('mjml-clear')
        }
        catch (e) {
            console.error('e',e)
        }
        setEditor(editorInstance)
    },[props.editInstance])
    return (
        <div id={'gjs-email'} className={'design-editor'}/>
    )
}
export default EmailPage;

💖子组件传递事件给父组件props绑定事件

同理我们也可以在props传递一个事件给props,在子组价触发即可

💖父组件触发子组件的事件Ref

父组件 App.txs 使用ref获取组件实例

import './App.css';
import 'grapesjs/dist/css/grapes.min.css';
import grapesjs from 'grapesjs';
import { useState,useEffect,useRef } from 'react';
function App() {
  const emailRef:any=useRef();
  useEffect(()=>{console.log(emailRef)},[emailRef])
  return (
      <div className="App">
        <EmailPage editInstance={grapesjs} ></EmailPage>
      </div>
  );
}
export default App;

子组件 EmailPage.txs使用useImperativeHandle 暴露方法和属性

暴露两个方法分别是 getHtml和getBodyContent,最后使用forwardRef抛出组件实例

import grapesJSMJML  from '../components/email-edit/index'
import { forwardRef, useEffect, useState,useImperativeHandle } from 'react'
import zh from "../components/email-edit/locale/zh";
const EmailPage=(props:any,ref:any)=>{
    const [editor,setEditor]=useState();
    const [domRef,setDomRef]=useState();
    useEffect(()=>{
        const editorInstance:any = props.editInstance
            .init({
                fromElement: true,
                container: '#gjs-email',
                plugins: [grapesJSMJML ],
            });
        try{
            editorInstance.Commands.run('mjml-clear')
        }
        catch (e) {
            console.error('e',e)
        }
        setEditor(editorInstance)
    },[props.editInstance])
    const getBodyContent=()=>{
        // @ts-ignore
        const inlineHtml=editor.Commands.run('mjml-code-to-html-inline')
        const matchBody=new RegExp('<body[^>]*>([\\s\\S]+?)<\\/body>','ig');
        const matchBodyText=inlineHtml.match(matchBody)
        // @ts-ignore
        return matchBodyText?matchBodyText[0]:''
    };
    const getHtml=()=>{
        // @ts-ignore
        return editor.Commands.run('mjml-code-to-html-inline')
    }
    useImperativeHandle(ref, () => ({
        getHtml:getHtml,
        getBodyContent:getBodyContent
    }));
    return (
        <div id={'gjs-email'} className={'design-editor'}
             ref={(ref:any)=>{
                 setDomRef(ref)
             }}
        />
    )
}
export default forwardRef(EmailPage);

⭐vue3 组件传值实例

项目截图

💖 父组件传递数据给子组件props

子组件 defineProps 定义接受的参数

IframeContent.vue

<template>
  <div class="iframe-container">
    <div class="iframe-content" v-if="!isPage&&!isModel">
      <div style="width: 100%">
        <span> 标题:{{ title }} </span>
        {{kind}}
        <a-button
          @click="jumpPage"
          type="primary"
          style="float: right; margin: 5px"
        >
          跳转</a-button
        >
      </div>
      <iframe :src="url" class="iframe-box"></iframe>
    </div>
    <div class="iframe-content" v-else-if="!isModel">
      <UserTable></UserTable>
    </div>
    <div class="iframe-content" v-else>
      <ChatTable></ChatTable>
    </div>
  </div>
</template>
<script lang="ts" setup>
import {computed} from 'vue'
// @ts-ignore
const props = defineProps<{
  url: string;
  title: string;
  kind: string;
}>();
const isPage=computed(()=>{
  console.log('props',props)
  return props.kind=='page'
})
const isModel=computed(()=>{
  console.log('props',props)
  return props.kind=='model'
})
const emit = defineEmits<{
  (e: "change", id: number): void;
  (e: "update", value: string): void;
}>();
const jumpPage = () => {
  window.open(props.url);
};
</script>

父组件 标签内传递数据给子组件

传递参数给iframe-content组件

<script setup lang="ts">
// @ts-ignore
import IframeContent from "../iframe/IframeContent.vue";
import { reactive} from "vue";
interface contentType {
  url: string;
  title: string;
  kind:string;
}
const contentConfig: contentType = reactive({
  url: "url",
  title: "title",
  kind:'kind'
});
</script>
<template>
  
          <iframe-content
            :url="contentConfig.url"
            :title="contentConfig.title"
            :kind="contentConfig.kind"
          />
</template>


vue3、react组件数据传值对比分析——父组件传递子组件,子组件传递父组件(二)https://developer.aliyun.com/article/1492685


目录
相关文章
|
25天前
|
前端开发 UED 索引
React 图片灯箱组件 Image Lightbox
图片灯箱组件是一种常见的Web交互模式,用户点击缩略图后弹出全屏窗口展示大图,并提供导航功能。本文介绍了基于React框架的图片灯箱组件开发,涵盖初始化状态管理、图片加载与预加载、键盘和鼠标事件处理等常见问题及解决方案。通过`useState`和`useEffect`钩子管理状态,使用懒加载和预加载优化性能,确保流畅的用户体验。代码案例展示了组件的基本功能实现,包括打开/关闭灯箱、切换图片及键盘操作。
124 80
|
9天前
|
移动开发 前端开发 JavaScript
React 视频播放控制组件 Video Controls
本文介绍了如何使用 React 构建视频播放控制组件(Video Controls),涵盖基本概念、创建步骤和常见问题解决。首先,通过 HTML5 `&lt;video&gt;` 标签和 React 组件化思想,实现播放/暂停按钮和进度条等基础功能。接着,详细讲解了初始化项目、构建 `VideoControls` 组件及与主应用的集成方法。最后,针对视频无法播放、控制器状态不同步、进度条卡顿和音量控制失效等问题提供了具体解决方案,并介绍了全屏播放和自定义样式等进阶功能。希望这些内容能帮助你在实际项目中更好地实现和优化视频播放功能。
81 40
|
24天前
|
移动开发 前端开发 JavaScript
React 视频播放器组件:Video Player
本文介绍了如何使用 React 和 HTML5 `&lt;video&gt;` 标签构建自定义视频播放器组件。首先,通过创建基础的 React 项目和 VideoPlayer 组件,实现了基本的播放、暂停功能。接着,探讨了常见问题如视频加载失败、控制条样式不一致、性能优化不足及状态管理混乱,并提供了相应的解决方案。最后,总结了构建高效视频播放器的关键要点,帮助开发者应对实际开发中的挑战。
98 27
|
27天前
|
前端开发 JavaScript API
React 图片放大组件 Image Zoom
本文介绍如何使用React创建图片放大组件(Image Zoom),提升用户体验。组件通过鼠标悬停或点击触发放大效果,利用`useState`管理状态,CSS实现视觉效果。常见问题包括图片失真、性能下降和移动端支持,分别可通过高质量图片源、优化事件处理和添加触摸事件解决。易错点涉及状态管理混乱、样式冲突和过多事件绑定,建议使用上下文API、CSS模块及优化事件绑定逻辑。高级功能扩展如多张图片支持和自定义放大区域进一步丰富了组件的实用性。
57 25
|
23天前
|
存储 编解码 前端开发
React 视频上传组件 Video Upload
随着互联网的发展,视频内容在网站和应用中愈发重要。本文探讨如何使用React构建高效、可靠的视频上传组件,涵盖基础概念、常见问题及解决方案。通过React的虚拟DOM和组件化开发模式,实现文件选择、进度显示、格式验证等功能,并解决跨域请求、并发上传等易错点。提供完整代码案例,确保用户能顺畅上传视频。
127 92
|
28天前
|
移动开发 前端开发 JavaScript
React 图片裁剪组件 Image Cropper
本文介绍了在React中实现图片裁剪功能的方法,涵盖基础知识、常见问题及解决方案。首先,通过第三方库如`react-image-crop`或`cropperjs-react`可轻松实现图片裁剪。接着,针对性能和兼容性问题,提供了优化图片加载、处理裁剪区域响应慢、解决浏览器差异等方案。最后,通过代码案例详细解释了如何创建一个基本的图片裁剪组件,并提出了优化建议,如使用`React.memo`、添加样式支持及处理大图片预览,帮助开发者避免常见错误并提升用户体验。
116 67
|
4天前
|
移动开发 前端开发 UED
React 音频预览组件:Audio Preview
本文介绍如何使用 React 构建音频预览组件,涵盖基础实现、常见问题及解决方案。通过 HTML5 `&lt;audio&gt;` 标签和 React 状态管理,实现播放控制。解决文件路径、浏览器兼容性等问题,并优化性能,避免状态不同步和内存泄漏,提升用户体验。
52 22
|
6天前
|
移动开发 前端开发 UED
React 音频播放器组件 Audio Player
本文介绍如何使用React创建功能丰富的音频播放器组件。基于HTML5 `&lt;audio&gt;` 标签,结合React的状态管理和事件处理,实现播放、暂停、进度和音量控制等功能。通过代码示例展示基本实现,并探讨常见问题如自动播放限制、进度条不更新、文件加载失败及多实例冲突的解决方案。同时,避免易错点如忽略生命周期管理、错误处理和性能优化,确保高效开发与良好用户体验。
59 23
|
8天前
|
缓存 前端开发 JavaScript
React 视频弹幕组件 Video Danmaku
本文介绍了如何在React中构建视频弹幕组件,提升用户观看体验和互动性。首先通过Create React App初始化项目,并集成`react-player`作为视频播放器。接着实现基本弹幕功能,包括评论的接收与显示,使用CSS动画实现滚动效果。针对常见问题如弹幕重叠、性能下降及同步问题,提供了随机化位置、分批加载和监听播放进度等解决方案。最后探讨了弹幕分类和特效等高级技巧,确保弹幕系统的高性能和良好用户体验。
48 23
|
26天前
|
存储 前端开发 索引
React 图片轮播组件 Image Carousel
本文介绍了如何使用React创建图片轮播组件。首先,解释了图片轮播的基本概念和组件结构,包括图片容器、导航按钮、指示器和自动播放功能。接着,通过代码示例详细说明了创建基本组件、添加自动播放、处理边界情况的步骤。还探讨了常见问题如状态更新不及时、内存泄漏和样式问题,并提供了解决方案。最后,介绍了进阶优化,如添加过渡效果、支持触摸事件和动态加载图片,帮助读者构建更完善的轮播组件。
47 16