根据Vue对比来深入学习React 上 函数组件 jsx 事件绑定 响应式数据 条件绑定 列表渲染 表单绑定

devtools/2024/10/17 16:49:33/

在这里插入图片描述

文章目录

      • React项目创建
      • React核心库介绍
      • React组件
      • jsx
        • 编写jsx代码的本质
        • jsx里面渲染不同内容
      • 事件绑定
        • 事件绑定其他操作
        • 特别注意
      • 响应式数据
        • `setState` 的特性
      • 条件渲染
      • 列表循环
      • 表单绑定
      • 总结

React项目创建

react官网提供了很多生产级的React框架
比如next.js,不过你还得学习next.js框架,
有点冗杂,下面文章会用vite来创建react项目

npx create-next-app@latest

使用create-react-app脚手架
此方法带警告 后续可能会删除

npx create-react-app app-name

使用vite创建,后续点React就行

pnpm create vite@latest

React核心库介绍

"dependencies": {
"react": "^18.3.1",
"react-dom": "^18.3.1"
},

React核心库:提供react的各个功能,比如生命周期,状态管理

react-dom:用于与浏览器的 DOM 进行交互提供一些dom操作方法用于把react创建出来的react对象挂载到真正的htmldom中,或者从htmldom中卸载。核心作用类似于vue的mount

//main.ts
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
//严格模式
<StrictMode>
<App />
</StrictMode>
)
//vue3中
import { createApp } from 'vue'; import App from './App.vue'; createApp(App).mount('#app');

我们可以看到:React 更加强调函数式编程hooks的使用,而 Vue 3 提供了更为直观的模板语法和灵活的 API

React组件

React的组件分类:

  1. 函数组件
//组件首字母一定要大写
function Test(){return <div></div>
}
  1. 类组件 淘汰了 不做过多赘述
import React, { Component } from 'react';class SimpleCounter extends Component {render() {return (<div><div>hello class</div></div>);}}
export default SimpleCounter;

jsx

React项目利用babel做了对js的编译,所以我们是可以直接在js里混用jsx的

jsx和js一样,不同点就在于,可以更方便的写html在is里,写在js里的html最后会被编译成一个js对象,我们也可以用react自带createElement创建这个对象

编写jsx代码的本质
  1. 使用jsx 一个组件 加上尖括号当成html使用
  2. 写一段html
  3. 不借助jsx,直接用react.createElement方法
    react.createElement与vue中h方法类似都是创建生成虚拟 DOM 节点
    最后都会转化为React-element对象,让React解析对象,创建成页面。
jsx里面渲染不同内容
  • 字符串,数字都是直接渲染
  • 无法渲染方法
  • 对象 只能渲染element对象
  • 布尔值 不渲染任何内容
  • 数组 把数组里的每一项单独渲染
  • undefine,null 不渲染任何内容
  • 表达式 直接运行

事件绑定

在 React 中,事件处理函数通常是在 JSX 中直接绑定的,并且使用驼峰语法。比如onClick

而Vue中都是通过指令简写@。比如@click

//react
import React from 'react';
const MyComponent = () => {
const handleClick = () => {
console.log('Button clicked!');
};
return (
<button onClick={handleClick}>Click Me</button>
);
};
export default MyComponent;//vue
<template>
<button @click="increment">Click Me</button>
<p>count</p>
<template>
<script setup>const count = ref(0); // 定义方法const increment = () => { count.value++; };
<script>
事件绑定其他操作

我们知道在Vue中直接传递参数就行了,那么在react又该怎么做呢?

<template><div><button @click="handleClick(1, $event)">Click Me</button></div></template><script setup>handleClick(param, event) {// 1. 传递参数console.log('Parameter:', param);// 2. 获取事件对象console.log('Event:', event);console.log('Target:', event.target); // 事件目标// 3. 阻止默认行为和冒泡event.preventDefault(); // 阻止默认行为event.stopPropagation(); // 阻止事件冒泡// 可以在这里执行其他操作console.log('Default behavior prevented and event propagation stopped.');}</script>
  1. 传递参数
    方法传递参数时使用箭头函数包裹
const App = () => {const handleClick = (param) => {console.log(param);};
return (<div><button onClick={() => handleClick('Hello, World!')}>Click Me</button></div>);};
  1. 获取事件对象
//无参时
const App = () => {const handleClick = (event) => {console.log('Event:', event);console.log('Button clicked:', event.target);};
return (<div><button onClick={handleClick}>Click Me</button></div>);
//有参数时
function App() {const handleClick = function(a:number,b:number,e:any){console.log(a,b,e,e.target);}return (<><button onClick={(e) => handleClick(1,2,e)}></button></>)}export default App
  1. 阻止默认行为,冒泡等
import React from 'react';const App = () => {const handleSubmit = (event) => {event.preventDefault(); // 阻止表单提交console.log('Form submitted');};const handleButtonClick = (event) => {event.stopPropagation(); // 阻止事件冒泡console.log('Button clicked');};return (<form onSubmit={handleSubmit}><button onClick={handleButtonClick}>Submit</button></form>);};export default App;
特别注意

与Vue中的不同给到事件绑定的一定是一个方法,不要直接调用方法,调用方法会使页面初次渲染指向方法

响应式数据

React 不能像 Vue 一样直接修改触发更新
Vue:Vue 使用的是数据代理,当你直接修改数据属性时,Vue 的响应式系统会自动监测到这些变化,并触发视图的更新。这是因为 Vue 在内部使用Object.defineProperty 或 Proxy 来拦截对对象的访问和修改。
React:React 不会自动追踪数据的变化。如果你直接修改组件的状态(如通过直接赋值)React 并不会知道需要重新渲染组件。要触发更新,必须使用 setState()或 相应的Hooks 。这是因为 React 采用了声明式编程模型,更新状态后 React 会重新计算出需要渲染的组件

react修改能改值,但无法触发更新,因为react没有像vue一样监听get和set,而是在调用setState或相应的Hooks的时候调用的更新操作

import React, { useState } from 'react';const Counter = () => {const [count, setCount] = useState(0);return (<button onClick={() => setCount(count + 1)}>{count}</button>);};
export default Counter;
//输入框
import React, { useState } from 'react';const TextInput = () => {const [inputValue, setInputValue] = useState('');const handleChange = (event) => {setInputValue(event.target.value);};return (<div><input type="text" value={inputValue} onChange={handleChange} /><p>You typed: {inputValue}</p></div>);};export default TextInput;

浅合并 在开发中常用

const UserForm = () => {const [formData, setFormData] = useState({name: '',age: '',email: ''});
// 处理输入变化const handleChange = (event) => {const { name, value } = event.target;// 使用浅合并来更新状态setFormData((prevData) => ({...prevData, // 浅合并之前的状态[name]: value // 更新特定字段}));};
setState 的特性
  1. 合并更新
const handleClick = () => {setCount(count + 1); setCount(count + 2); // 只有这次会生效};
//最后会为2
  1. 触发更新
    如果 newValue 等于当前 value,组件依然会重新渲染,这可能会影响性能,尤其是在频繁调用的情况下
const updateValue = (newValue) => { 
setValue(newValue);// 即使新值与当前值相同 };

r解决办法: 给个条件判断 使用函数式更新 或者调用useCallbalck和useMemo优化函数和计算值

const MyComponent = () => {const [count, setCount] = useState(0);const increment = () => {const newCount = count + 1;if (newCount !== count) {setCount(newCount);}};const MyComponent = () => {const [count, setCount] = useState(0);const increment = () => {setCount(prevCount => prevCount + 1); // 返回新的状态,避免直接依赖 count};const MyComponent = () => {const [count, setCount] = useState(0);const increment = useCallback(() => {setCount(prevCount => prevCount + 1);}, []);
  1. 避免在render方法中使用
    render 方法中直接调用 setState 会导致无限循环,因为每次组件渲染都会调用 setState,从而触发新的渲染。这是非常不推荐的做法。正确的方法是在事件处理或生命周期方法中调用 setState
const MyComponent = () => {
const [count, setCount] = useState(0);
// 不要这样做:
// setCount(count + 1); // 会导致无限循环
return (<div><p>{count}</p><button onClick={() => setCount(count + 1)}>Increment</button></div>);
};

在 React 中,使用 setState 来更新数组和对象时,确实需要返回一个新的数组或对象。这是因为 React 使用浅比较来检测状态的变化,如果你直接修改原有的状态对象或数组,React 可能不会意识到这些变化,从而不触发重新渲染

import React, { useState } from 'react';const MyComponent = () => {const [state, setState] = useState({ name: 'zhaimou', age: 30 });const updateName = () => {setState(prevState => ({...prevState,name: 'zhai'}));};return (<div><p>Name: {state.name}</p><p>Age: {state.age}</p><button onClick={updateName}>Change Name</button></div>);};

条件渲染

在 Vue 中,条件渲染通常使用 v-ifv-else-ifv-else 指令。Vue 的模板语法使得条件渲染更加直观。

在 React 中,通常使用 JavaScript 表达式来进行条件渲染。可以使用 if 语句、三元运算符或者逻辑与(&&)操作符。

import React, { useState } from 'react';const MyComponent = () => {const [isLoggedIn, setIsLoggedIn] = useState(false);return (<div>{isLoggedIn ? (<h1>Welcome back!</h1>) : (<h1>Please log in.</h1>)}<button onClick={() => setIsLoggedIn(!isLoggedIn)}>Toggle Login</button></div>);};

列表循环

在 Vue 中,使用 v-for 指令进行列表渲染。与 React 类似,Vue 也要求每个列表项有一个唯一的 key 属性。

在 React 中,通常使用 map() 方法来遍历数组并生成组件。每个元素需要一个唯一的 key 属性以帮助 React 识别哪些项发生了变化、被添加或删除。

import React from 'react';const ItemList = ({ items }) => {return (<ul>{items.map((item, index) => (<li key={item.id}>{item.name}</li> // 使用唯一的 id 作为 key))}</ul>);};export default ItemList;

表单绑定

在 Vue 中,表单元素使用 v-model 指令进行双向数据绑定,@submit.prevent阻止默认的提交行为事件修饰符绑定

在 React 中,表单元素通常是“受控组件”,这意味着表单的值由 React 的状态管理。

import React, { useState } from 'react';const MyForm = () => {const [name, setName] = useState('');// 处理输入框的变化const handleChange = (event) => {setName(event.target.value); // 更新状态为输入框的当前值};// 处理表单提交const handleSubmit = (event) => {event.preventDefault(); // 阻止默认的表单提交行为alert(`提交的名称: ${name}`);};return (<form onSubmit={handleSubmit}><label>名称:<input type="text" value={name} onChange={handleChange} /> {/* 受控组件 */}</label><button type="submit">提交</button></form>);};export default MyForm;

总结

Vue各种效果用指令编写,对于简单的控制非常容易
React各种效果都通过逻辑运算产出对应的内容渲染 能够完整控制整个过程 更少的封装,更高的自由度

本篇文章到这里就结束了 如果对你有所帮助就点个关注吧 会持续更新技术文章


http://www.ppmy.cn/devtools/124945.html

相关文章

Python知识点:基于Python技术,如何使用OpenCV进行道路标志识别

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 使用OpenCV进行道路标志识别的Python技术详解 道路标志识别是智能交通系统中的应…

【动手学深度学习】6.4 多输入多输出通道

彩色图像具有标准的RBG通道来代表红绿蓝&#xff0c;但是到目前位置我们仅展示了单个输入和单个通道的简化例子。这使得我们可以将输入&#xff0c;卷积核和输出看作二维张量而当我们添加通道时&#xff0c;输入和隐藏表示都变成了三维张量。例如每个RGB输入图像都具有 3 h …

【云从】三、计算机网络基础

文章目录 1、网络2、网络通信2.1 IP地址2.2 子网掩码2.3 网关2.4 私有地址和公有地址2.5 NAT网络地址转换 3、网络架构及设备 1、网络 网络&#xff0c;即通过通信线路&#xff08;如光纤、网线&#xff09;和通信设备&#xff08;如路由器、光猫&#xff09;&#xff0c;将各…

对偶范数(Dual Norm)

文章目录 1. 对偶范数的定义2. 常见范数和对偶范数的关系3. 直观理解4. 示例5. 应用场景6.总结 对偶范数&#xff08;Dual Norm&#xff09; 是在泛函分析和凸优化中非常重要的概念。它用于衡量向量和线性函数之间的关系&#xff0c;尤其是在优化问题和范数的几何理解中非常有用…

Rider 编译 UE5 项目 MSBuild 报错解决

报错信息&#xff1a; CONSOLE: Use build tool: D:\Work\Microsoft Visual Studio\MSBuild\Current\Bin\amd64\MSBuild.exe Microsoft.NET.Sdk.ImportWorkloads.props(14,3): Error : 无法解析 SDK“Microsoft.NET.SDK.WorkloadAutoImportPropsLocator”。下面的探测消息中正…

Vue3和Vue2的区别

根标签 Vue2 Templata只支持一个根标签 <template><div></div> </template>Vue3 Templata支持多个根标签 <template><div></div><img/> </template>初始化方法 Vue2 使用 new Vue(), 参数是new Vue({template, render})…

LibreOffice SDK是LibreOffice软件的开发工具包

LibreOffice SDK是LibreOffice软件的开发工具包&#xff0c;它提供了一系列工具和库&#xff0c;使得开发者可以基于LibreOffice进行扩展或开发新的应用程序。以下是对LibreOffice SDK的详细介绍&#xff1a; 一、下载与安装 下载地址&#xff1a; 可以在LibreOffice的官方网站…

十一、数据库的设计规范

文章目录 1. 为什么需要数据库设计2. 范式2.1 范式介绍2.2 范式都包括哪些2.3 键和相关属性的概念2.4 第一范式(1st NF)2.5 第二范式(2nd NF)2.6 第三范式(3rd NF)2.7 小结3. 反范式化3.1 概述3.2 应用举例3.3 反范式的新问题3.4 反范式的使用场景3.4.1 增加冗余字段的建议3.…