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

文章目录

    • ⭐前言
    • ⭐react 组件传值实例
      • 💖父组件传值给子组件(props)
      • 💖子组件传递事件给父组件props绑定事件
      • 💖父组件触发子组件的事件Ref
    • ⭐vue3 组件传值实例
      • 💖 父组件传递数据给子组件props
      • 💖 子组件传递事件给父组件使用emit
      • 💖 父组件获取子组件实例使用Ref
    • ⭐总结
    • ⭐结束

yma16-logo

⭐前言

大家好,我是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 组件传值实例

项目截图
email-template

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

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

react-demo
父组件 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-ignoreconst inlineHtml=editor.Commands.run('mjml-code-to-html-inline')const matchBody=new RegExp('<body[^>]*>([\\s\\S]+?)<\\/body>','ig');const matchBodyText=inlineHtml.match(matchBody)// @ts-ignorereturn matchBodyText?matchBodyText[0]:''};const getHtml=()=>{// @ts-ignorereturn 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 组件传值实例

项目截图
vue3-back-front

💖 父组件传递数据给子组件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>

💖 子组件传递事件给父组件使用emit

子组件

<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>

父组件通过@绑定事件change和update就能接受子组件触发的change和update事件

💖 父组件获取子组件实例使用Ref

通过使用ref绑定formRef去获取校验事件

<template><div class="container"><div class="loginUser-container"><div class="loginUser-title">管理平台</div><a-form:model="state.formState":label-col="state.layoutConfig.labelCol":wrapper-col="state.layoutConfig.wrapperCol":rules="state.formRule"ref="formRef"layout="vertical"autocomplete="off"><a-form-item label="账号" name="username"><a-inputv-model:value="state.formState.username"allowClearplaceholder="请输入账号":disabled="state.spinning"/></a-form-item><a-form-item label="密码" name="password"><a-input-passwordv-model:value="state.formState.password":disabled="state.spinning"allowClearplaceholder="请输入密码"/></a-form-item><a-form-item name="remember" :wrapper-col="state.wrapperCol"><a-checkboxv-model:checked="state.formState.remember":disabled="state.spinning">记住密码</a-checkbox></a-form-item><a-form-item :wrapper-col="state.submitWrapperCol" class="submit-box"><a-buttontype="primary"html-type="submit"@click="loginAction":loading="state.spinning"style="width: 100%; font-size: 16px; font-weight: bolder">登录</a-button></a-form-item></a-form><div class="description"><span class="description-prefix">没账号?</span><span@click="jumpRegister"class="description-after":disabled="state.spinning">去注册</span></div></div></div>
</template>
<script lang="ts" setup>
import { reactive, ref, onMounted } from "vue";
import { useRouter } from "vue-router";
import { useStore } from "vuex";
import { message } from "ant-design-vue";
import { loginUser } from "../../service/user/userApi";import type { FormInstance } from "ant-design-vue";interface FormStateType {username: string;password: string;remember: boolean;
}
interface FormRuleType {username: Object;password: Object;
}
interface stateType {formState: FormStateType;formRule: FormRuleType;layoutConfig: any;wrapperCol: any;submitWrapperCol: any;spinning: boolean;backgroundImgUrl: string;
}
// 路由
const router = useRouter();
//store
const store = useStore();
const formRef = ref<FormInstance>();
const state: stateType = reactive({formState: {username: "",password: "",remember: false,},spinning: false,formRule: {username: [{ required: true, message: "请输入账号!" }],password: [{ required: true, message: "请输入密码!" }],},layoutConfig: {labelCol: {span: 8,},wrapperCol: {span: 24,},},wrapperCol: { offset: 0, span: 24 },submitWrapperCol: { offset: 0, span: 24 },backgroundImgUrl:"http://www.yongma16.xyz/staticFile/common/img/background.png",
});
/*** 初始化表单内容*/
const initForm = () => {const userInfoItem: any = window.localStorage.getItem("userInfo");interface userInfoType {username: string;password: string;remember: boolean;}const userInfo: userInfoType = userInfoItem? JSON.parse(userInfoItem): {username: "",password: "",remember: false,};if (userInfo.username && userInfo.password) {state.formState.username = userInfo.username;state.formState.password = userInfo.password;state.formState.remember = userInfo.remember;}
};
/*** 前往注册!*/
const jumpRegister = () => {// 带 hash,结果是 /about#teamrouter.push({ path: "/register" });
};/*** 前往home!*/
const jumpHome = () => {// 带 hash,结果是 /about#teamrouter.push({ path: "/" });
};
/*** 记住密码* @param params*/
const rememberAction = (params: Object) => {window.localStorage.setItem("userInfo", JSON.stringify(params));
};
/*** 登录*/
const loginAction = () => {if (formRef.value) {formRef.value.validate().then(async (res: any) => {state.spinning = true;const params = {username: state.formState.username,password: state.formState.password,};if (state.formState.remember) {rememberAction({ ...params, remember: state.formState.remember });}try {console.log('登录',params)// @ts-ignoreawait store.dispatch("user/loginUser",params);// 跳转setTimeout(() => {jumpHome();}, 500);state.spinning = false;} catch (r: any) {message.error(JSON.stringify(r));state.spinning = false;throw Error(r);}});}
};onMounted(() => {//初始化initForm();
});
</script>

⭐总结

综合比较react和vue,对于选型我分成两种情况讨论。

  1. vue项目选型——vue3 vben admin
    a. 外包项目(可维护性强,中文文档多,容错率高)
    b. 国内开发者众多的团队,因为vue中文文档比较多
    c. 使用vue较多的团队,适合快速上手
  2. react项目——qiankun
    a. 自研大型项目(个人觉得react项目不好抄袭)
    b. 外企团队,因为react的文档大部分都是英文
    c. 使用react较多的团队,适合快速上手

个人比较看好vue,有以下3点。
a. 国内开发人数众多,搭建可以用中文在社区交流vue3,扩大国内开发影响力
b. vue3的组件传值等我都比react好用,react用的费劲
c. vue的生态良好,版本也一直在迭代更新

⭐结束

本文分享到这结束,如有错误或者不足之处欢迎指出!
cute-animal

👍 点赞,是我创作的动力!
⭐️ 收藏,是我努力的方向!
✏️ 评论,是我进步的财富!
💖 感谢你的阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/98406.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神经网络改进:注重空间变化,权重参数调整,正则化, 熵的简单理解

目录 神经网络改进&#xff1a;注重空间变化 将高纬空间映射到地位空间便于表示&#xff08;供给数据&#xff09; 将地位空间映射到高纬空间进行分类聚合&#xff08;达到可分状态&#xff08;K-means&#xff09;&#xff09; 神经网络改进&#xff1a;权重参数调整 自注…

PHP自己的框架实现操作成功失败跳转(完善篇四)

1、实现效果&#xff0c;操作成功后失败成功自动跳转 2、创建操作成功失败跳转方法CrlBase.php /**成功后跳转*跳转地址$url* 跳转显示信息$msg* 等待时间$wait* 是否自动跳转$jump*/protected function ok($urlNULL,$msg操作成功,$wait3,$jump1){$code1;include KJ_CORE./tp…

excel 核心快捷键用法

1、wps怎样只复制公示计算出来的数据 1.1、按下快捷键“CtrlC”&#xff0c;复制该单元格。 1.2、按下快捷键“ShiftCtrlV”&#xff0c;即“粘贴为数值”&#xff0c;即可只复制数字而不复制该单元格的公式 1.3、wps怎样只复制公示计算出来的数据_百度知道https://zhidao.baid…

C++ 的关键字(保留字)完整介绍

1. asm asm (指令字符串)&#xff1a;允许在 C 程序中嵌入汇编代码。 2. auto auto&#xff08;自动&#xff0c;automatic&#xff09;是存储类型标识符&#xff0c;表明变量"自动"具有本地范围&#xff0c;块范围的变量声明&#xff08;如for循环体内的变量声明…

GAN:对抗生成网络,前向传播和后巷传播的区别

目录 GAN&#xff1a;对抗生成网络 损失函数 判别器开始波动很大&#xff0c;先调整判别器 生成样本和真实样本的统一&#xff1a;真假难辨​编辑 文字专图片​编辑 头像转表情包​编辑 头像转3D​编辑 后向传播 1. 前向传播&#xff08;forward&#xff09; 2. 反向传播&…

windows权限维持—黄金白银票据隐藏用户远控RustDeskGotoHttp

windows权限维持—黄金白银票据&隐藏用户&远控&RustDesk&GotoHttp 1. 前置1.1. 初始问题1.1.1. 解决办法 2. 隐藏用户2.1. 工具原理2.2. 案例操作2.2.1. 单机添加用户2.2.1.1. 工具添加用户2.2.1.2. 工具查看隐藏用户2.2.1.3. 本地查看隐藏用户 2.2.2. 域内添加…

什么是Eureka?以及Eureka注册服务的搭建

导包 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0 htt…

WPF入门到精通:2.WPF常用控件及布局

WPF&#xff08;Windows Presentation Foundation&#xff09;是一个用于构建 Windows 应用程序的框架&#xff0c;它提供了丰富的控件和布局方式&#xff0c;帮助开发者快速构建出现代化的应用程序。 WPF常用控件 Button 控件 WPF 中最常用的控件之一。它由一个文本标签和一个…

nginx反向代理、负载均衡

修改nginx.conf的配置 upstream nginx_boot{# 30s内检查心跳发送两次包&#xff0c;未回复就代表该机器宕机&#xff0c;请求分发权重比为1:2server 192.168.87.143 weight100 max_fails2 fail_timeout30s; server 192.168.87.1 weight200 max_fails2 fail_timeout30s;# 这里的…

菜鸟Vue教程 - 实现带国际化的注册登陆页面

初接触vue的时候觉得vue好难&#xff0c;因为项目中要用到&#xff0c;就硬着头皮上&#xff0c;慢慢的发现也不难&#xff0c;无外乎画个布局&#xff0c;然后通过样式调整界面。在通过属性和方法跟js交互。js就和我们写的java代码差不多了&#xff0c;复杂一点的就是引用这种…

G0第26章:微服务概述与gRPCprotocol buffers

Go微服务与云原生 1、微服务架构介绍 单体架构&#xff08;电商&#xff09; SOA架构&#xff08;电商&#xff09; 微服务架构&#xff08;电商&#xff09; 优势 挑战 拆分 发展史 第一代:基于RPC的传统服务架构 第二代:Service Mesh(istio) 微服务架构分层 核心组件 Summar…

css学习3(三种样式表与样式控制优先级)

1、外部样式表&#xff1a;当样式需要应用于很多页面时&#xff0c;外部样式表将是理想的选择。在使用外部样式表的情况下&#xff0c;你可以通过改变一个文件来改变整个站点的外观。每个页面使用 <link> 标签链接到样式表&#xff0c;也要放到<head>中。 2、外部…

快速排序 | C++|时间空间复杂度

1.概念 快速排序(QuickSort)的基本思想是:通过一趟排序将待排记录分割成独立的两部分&#xff0c;其中一部分记录的关键字均比另一部分记录的关键字小&#xff0c;则可分别对这两部分记录继续进行排序&#xff0c;以达到整个序列有序的目的。 2.算法思想描述 1.进行一次划分&…

开源远程控制硬件 BliKVM v4测试 1000公里外远程重装系统

测试准备 测试时间&#xff1a;20230818 测试硬件&#xff1a;BliKVM v4 文档 BliKVM v4是一款生产就绪、即插即用的 KVM-over-IP 设备&#xff0c;为专业用户提供了远程服务器或工作站管理的便捷解决方案。 它基于Linux并且完全开源。 借助 BliKVM&#xff0c;您可以轻松打…

人工智能大模型加速数据库存储模型发展 行列混合存储下的破局

数据存储模型 ​专栏内容&#xff1a; postgresql内核源码分析手写数据库toadb并发编程toadb开源库 个人主页&#xff1a;我的主页 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 概述 在数据库的发展过程中&#xff0c;关…

改善神经网络——优化算法(mini-batch、动量梯度下降法、Adam优化算法)

改善神经网络——优化算法 梯度下降Mini-batch 梯度下降&#xff08;Mini-batch Gradient Descent&#xff09;指数加权平均包含动量的梯度下降RMSprop算法Adam算法 优化算法可以使神经网络运行的更快&#xff0c;机器学习的应用是一个高度依赖经验的过程&#xff0c;伴随着大量…

【CSS动画02--卡片旋转3D】

CSS动画02--卡片旋转3D 介绍代码HTMLCSS css动画02--旋转卡片3D 介绍 当鼠标移动到中间的卡片上会有随着中间的Y轴进行360的旋转&#xff0c;以下是几张图片的介绍&#xff0c;上面是鄙人自己录得一个供大家参考的小视频&#x1f92d; 代码 HTML <!DOCTYPE html>…

【idea】社区版idea运行Tomcat

使用 Smart Tomcat插件 配置运行&#xff1a;

解决Kibana(OpenSearch)某些字段无法搜索问题

背景 最近在OpenSearch查看线上日志的时候&#xff0c;发现某个索引下有些字段无法直接在界面上筛选&#xff0c;搜索到也不高亮&#xff0c;非常的不方便&#xff0c;就像下面这样 字段左侧两个筛选按钮禁用了无法点击&#xff0c;提示 Unindexed fields can not be searched…

MapReduce介绍

目录 ​一、什么是MapReduce 二、MapReduce 的设计思想 2.1 分而治之 2.2 构建抽象模型&#xff1a;Map和Reduce 2.3 隐藏系统层细节 三、MapReduce 的框架原理 3.1 MRv1工作原理 3.1.1 MRv1架构工作原理图 3.1.1.1 流程说明 3.1.1.1.1 作业的提交 3.1.1.1.2 作业的初始化 3…