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

ops/2024/10/18 5:42:35/

在这里插入图片描述

文章目录

      • 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/ops/124799.html

相关文章

springboot-网站开发-使用slf4j实现网站异常错误的及时跟踪定位

springboot-网站开发-使用slf4j实现网站异常错误的及时跟踪定位&#xff01;项目部署&#xff0c;开发好后&#xff0c;部署到远程服务器上面了&#xff0c;运行过程中&#xff0c;难免会遇到一些错误和异常情况&#xff0c;我们需要借助一些插件来帮助我们及时捕捉这类错误和异…

【中标麒麟】防火墙开放白名单

先打开防火墙&#xff0c;如果你已经开启则省略这步&#xff1a; sudo systemctl start firewalld sudo systemctl enable firewalld 检查防火墙状态&#xff1a; sudo firewall-cmd --state 打开一个服务&#xff1a; sudo firewall-cmd --permanent --add-servicehttp s…

JavaScript中的数组

1.数组的概念 数组可以把一组相关的数据一起存放&#xff0c;并提供方便的访问/获取方式数组是指一组数据的集合&#xff0c;其中每个数据称之为元素(element)&#xff0c;在数组中可以存放任意类型的元素&#xff0c;数组是一种将一组数据存储在单个变量名下的优雅方式。 2.…

计算机网络:数据链路层 —— 可靠传输服务

文章目录 可靠传输停止-等待 (SW) 协议超时重传机制分组编号机制ACK 丢失问题ACK 延迟问题 注意事项信道利用率 回退 N 帧 (GBN) 协议滑动窗口信道利用率无传输差错超时重传、回退N帧 累计确认 选择重传 (SR) 协议滑动窗口 可靠传输 若数据链路层向其上层提供的服务类型为可靠…

Ubuntu安装Mysql并实现远程登录【ubuntu 24.04/mysql 8.0.39】

一、安装MySQL sudo apt update # 更新软件源 sudo apt install mysql-server -y # 安装 mysql --version # 查看版本 sudo systemctl status mysql # 查看运行状态 netstat -tln # 以数字ip形式显示mysql的tcp监听状态二、设置MySQL的root密码 sudo mysql -u root # 使…

第1章 开发板功能及使用介绍

1.开发板功能及使用介绍 本章主要内容 1.开发板功能介绍 2.开发板使用方法 介绍 STM32介绍 本章主要内容&#xff1a; 1.什么是STM32 2.STM32与ARM的关系 3.STM32F407ZGT6介绍 4.STM32能做什么 1.什么是STM32 从字面意义来看&#xff1a; ST&#xff1a;意法半导体&#xf…

oracle操作回退SQL

对表数据进行操作后&#xff0c;提交了事务&#xff0c;发现数据更新或者删除错了&#xff0c;这时候还是有方法可以数据回退的 进行数据回退操作&#xff0c;将数据回退到xxxx分钟&#xff0c;也就是update操作之前&#xff1a; 在回退之前&#xff0c;先查询xx分钟的数据&…

vscode播放MP4文件时候没声音

问题描述&#xff1a; vscode 播放MP4文件时候没有声音 原因分析&#xff1a; https://github.com/microsoft/vscode-docs/blob/vnext/release-notes/v1_72.md#built-in-preview-for-some-audio-and-video-files 解决方案&#xff1a; 从上面描述可以看出&#xff0c;大概…