文章目录
- 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的组件分类:
- 函数组件
//组件首字母一定要大写
function Test(){
return <div></div>
}
- 类组件 淘汰了 不做过多赘述
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代码的本质
- 使用jsx 一个组件 加上尖括号当成html使用
- 写一段html
- 不借助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>
- 传递参数
方法传递参数时使用箭头函数包裹
const App = () => {
const handleClick = (param) => {
console.log(param);
};
return (
<div>
<button onClick={() => handleClick('Hello, World!')}>
Click Me
</button>
</div>
);
};
- 获取事件对象
//无参时
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
- 阻止默认行为,冒泡等
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
的特性
- 合并更新
const handleClick = () => {
setCount(count + 1);
setCount(count + 2); // 只有这次会生效
};
//最后会为2
- 触发更新
如果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);
}, []);
- 避免在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-if
、v-else-if
和 v-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各种效果都通过逻辑运算产出对应的内容渲染 能够完整控制整个过程 更少的封装,更高的自由度
本篇文章到这里就结束了 如果对你有所帮助就点个关注吧 会持续更新技术文章