一. React 创建命令
- 官方推荐:Vite 创建(最快、最现代)
npm create vite@latest
- 传统方式:Create React App(CRA)老项目常用,配置简单、生态成熟
npx create-react-app my-react-app
二. jsx
概念: jsx 是js和xml(html) 的缩写,表示在js代码中编写html模版结构,它是react中编写ui模版的方式
javascript
const message='this is message'
function App(){
return (
<div>
<h1> this is title </h1>
{message}
</div>
)
}
优势:
- html的声明式模版写法 2. js的可编程能力
2.1 jsx本质
jsx 并不是标准的js语法,它是js的语法扩展,浏览器本身不能识别,需要通过解析工具做解析之后才能在浏览器中运行

2.2 jsx中使用js表达式
在jsx中可以通过大括号语法{ } 识别js中的表达式,比如常见的变量,函数调用,方法调用等等
-
使用引号传递字符串
-
使用js变量
-
函数调用和方法调用
-
使用 js对象
javascript
function getName(){
console.log(111)
return '我是名字'
}
const count='111'
function App() {
return (
<div>
{/* 用引号传递字符串 */}
{'this is message'}
{/* 识别js 变量 */}
{count}
{/* 函数调用 */}
{getName()}
{/* 方法调用 */}
{new Date().getDate()}
{/* 使用js对象 */}
<div style={{color:'red'}}>this is div</div>
</div>
)
}
export default App
注意: if 语句,switch 语句,变量声明属于语句,不是表达式,不能出现在{ } 中
2.3 jsx 使用列表渲染
javascript
const list = [
{ id: 1, name: '第一条数据' },
{ id: 2, name: '第二条数据' },
{ id: 3, name: '第三条数据' }
]
function App() {
return (
// 渲染列表
// map 循环哪个结构 就return 哪个结构
// 注意事项: 加上一个独一无二的key 字符串或者number id
// key的作用: react框架内部使用 提升更新性能的
<ul>
{list.map(item=><li key={item.id}>{item.name}</li>)}
</ul>
)
}
2.4 实现基础条件渲染
javascript
const isLogin = true
function App() {
return (
<div className="App">
逻辑与 &&
{isLogin && <span>aaa</span>}
三元运算
{isLogin? <span>sdklaj </span>:<span></span>}
</div>
)
}
2.5 实现复杂条件渲染
javascript
// 根据文章不同渲染不同的div
const type = 1
function getType() {
if (type === 1) {
return <div>萨迪克辣椒</div>
} else if (type === 2) {
return <div>文章类型2</div>
} else if (type === 3) {
return <div>文章类型3</div>
} else {
return <div>未知类型</div>
}
}
function App() {
return (
<div className="App">
{getType()}
</div>
)
}
export default App
2.6 点击事件
javascript
// const handleClick=()=>{
// console.log('button按钮被点击了')
// }
//事件参数e
// const handleClick=(e)=>{
// console.log('button按钮被点击了',e)
// }
// //传递自定义参数
// const handleClick=(name)=>{
// console.log('button按钮被点击了',name)
// }
//自定义参数 + 事件对象e
const handleClick=(name,e)=>{
console.log('button按钮被点击了',e)
}
function App() {
return (
<div className="App">
<button onClick={(e)=>handleClick('jack',e)}>click me</button>
</div>
)
}
三. 组件
3.1 在React中,一个组件就是首字母大写的函数,内部存放了组件的逻辑和视图UI,渲染组件只需要把组件当成标签书写即可
javascript
//定义组件
const Button =()=>{
//业务逻辑组件逻辑
return <button>click me!</button>
}
function App() {
return (
<div className="App">
{/* 使用组件(渲染组件) */}
{/* 自闭和 */}
<Button/>
{/* 成对标签 */}
<Button></Button>
</div>
)
}
export default App
四. useState 基础使用
useState 是一个React Hook(函数),它允许我们向组件添加一个状态变量,从而控制影响组件的渲染结果
count = 0 ===> 0
count = 1 ===> 1
本质: 和普通JS变量不同的是,状态变量一旦发生变化组件的视图UI也会跟着变化(数据驱动视图)
javascript
const [count,setCount] = useState(0)
-
useState 是一个函数,返回值是一个数组
-
数组中第一个参数是状态变量,第二个参数是set函数用来修改状态变量
-
useState的参数将作为count的初始值
4.1 用useState 实现一个计数器
javascript
// useState 实现一个计数器按钮
import { useState } from 'react'
function App() {
//1. 调用useState 添加一个状态变量
//count 状态变量
//setCount 修改状态变量的方法
const [count,setCount] =useState(0)
//2. 点击事件回调
const handleClick=()=>{
// 作用: 1. 用传入的新值修改count
//2. 重新使用心得count渲染UI
setCount(count + 1)
}
return (
<div> <button onClick={handleClick}></button>{count}</div>
)
}
export default App
4.2 状态不可变
在React中,状态被认为是只读的,我们应该始终替换它而不是修改它,直接修改状态不能引发视图更新
- 直接修改 无法引发视图更新
javascript
let [count,setCount] = useState(0)
const handleClick=()=>{
//直接修改 无法引发视图更新
count ++
console.log(count)
}
- 用传入的新值修改count, 重新使用新的count渲染UI
javascript
const handleClick=()=>{
setCount(count + 1)
}
4.3 修改对象状态
对于对象类型的状态变量,应该使用传给set方法一个全新的对象来进行修改
- 直接修改原对象,不引发视图变化
javascript
//直接修改原对象,不引发视图变化
const [form,setForm] = useState({
name: 'jack',
})
const handleChangeName=()=>{
form.name='john'
}
- 调用set传入新对象用于修改
javascript
const [form,setForm] = useState({
name: 'jack',
})
const handleChangeName=()=>{
setForm({
...form,
name:'john'
})
}
五. 基础样式控制
5.1 行内样式style
javascript
function App() {
return (
<div style={{
color:"red",
fontSize:'20px',
backgroundColor:"#f5f5f5",
padding: '10px'
}}>
行内样式
</div>
)
}
5.2. 在组件中导入使用
javascript
import './App.css'
function App(){
return <div className='box'>外部 CSS 样式 </div>
}
注意: React 用className 代替class
5.3 动态className
.active {
color: red;
font-weight: bold;
}
javascript
import {useState} from 'react'
import './App.css'
function App(){
const [active,setActive] = useState(false)
return(
<div className={active ? 'active' :''} onClick={()=>setActive(!active)}>
点击切换类名
</div>
)
}
5.4 多个class 拼接(常用)
javascript
// 普通写法
<div className={`box ${active ? 'active' : ''}`}}>
//或者用classnames 库
import classNames from 'classnames'
<div className = {classNames('box',{active:active})}>
六. 案例
6.1 评论列表渲染

javascriptimport { useState } from "react"; import "./App.css"; import _ from 'lodash'; const list = [ { rpid: 1, user: { avatar: 'sxxxx', uid: '30009257', uname: 'react' }, content: '哇,这个组件写得太丝滑了!学到了!', ctime: '04-14 10:30:25', like: 256 }, { rpid: 2, user: { uid: '13258166', avatar: 'http://toutiao.itheima.net/resources/images/avatar2.jpg', uname: 'Vue' }, content: '确实不错,不过Vue的写法也很优雅,各有千秋~', ctime: '04-14 09:45:10', like: 188 }, { rpid: 3, user: { uid: '13258167', avatar: 'http://toutiao.itheima.net/resources/images/avatar3.jpg', uname: 'TypeScript' }, content: '建议加上严格模式,不然大型项目容易出Bug🤣', ctime: '04-14 08:20:05', like: 99 }, { rpid: 4, user: { uid: '13258168', avatar: 'http://toutiao.itheima.net/resources/images/avatar4.jpg', uname: '前端老码农' }, content: '点赞!这种业务场景的实战讲解最接地气了!', ctime: '04-14 07:15:30', like: 120 }, { rpid: 5, user: { uid: '13258169', avatar: 'http://toutiao.itheima.net/resources/images/avatar5.jpg', uname: 'uni-app开发者' }, content: '大佬什么时候出一期跨端兼容的教程?坐等!🚀', ctime: '04-14 06:05:45', like: 210 } ]; // 当前登录用户 const user = { uid: '30009257', avatar: 'sxxxx', uname: 'react' }; // 导航 Tab const tabs = [ { type: "hot", text: "最热" }, { type: 'time', text: '最新' } ]; function App() { const [commentList, setCommentList] = useState(_.orderBy(list, 'like', 'desc')); const [activeType, setActiveType] = useState('hot'); // 删除功能 const handleDel = (id) => { setCommentList(commentList.filter(item => item.rpid !== id)); }; // 切换排序 const handleTabChange = (type) => { setActiveType(type); if (type === 'hot') { setCommentList(_.orderBy(commentList, 'like', 'desc')); } else { setCommentList(_.orderBy(commentList, 'ctime', 'desc')); } }; return ( <div className="app"> {/* 顶部导航 */} <div className="title"> <div>评论</div> <div className="nav"> {tabs.map(item => ( <span key={item.type} onClick={() => handleTabChange(item.type)} className={`nav-item ${activeType === item.type ? 'active' : ''}`} > {item.text} </span> ))} </div> </div> {/* 评论列表 */} <div className="body"> {commentList.map(item => ( <div className="comment-item" key={item.rpid}> <div className="uname">{item.user.uname}</div> <div className="content">{item.content}</div> <div className="time">{item.ctime}</div> {/* 仅自己显示删除按钮 */} {user.uid === item.user.uid && ( <span className="del" onClick={() => handleDel(item.rpid)}> 删除 </span> )} </div> ))} </div> </div> ); } export default App;
七. 表单
7.1 受控绑定表单
受控表单=表单元素的value 完全由React状态(state)控制
- 输入框显示什么 - > 看value
- 输入框变了 -> 触发 onChange -> 更新state
- 数据由React全权管理
javascript
// 1. 用 state 管理数据
const [value, setValue] = useState('')
// 2. value 绑定 state
// 3. onChange 更新 state
<input
type='text'
value={value}
onChange={(e)=>setValue(e.target.value)}
/>
7.2 非受控表单
非受控表单=表单自己管自己,React 不控制
- 数据存在DOM里
- 用useRef 获取值
- 不用state, 不用onChange
javascript
import {useRef} from "react";
// React 中获取dom
// 1. useRef生成ref对象 ,绑定到dom标签身上
// 2. dom可用时,ref.current 获取dom
// 渲染完毕之后dom生成之后才可用
function App() {
const inputRef = useRef(null)
const showDom=()=>{
console.dir(inputRef.current)
}
return (
<div>
<input type='text' ref={inputRef} />
<button onClick={showDom}>获取dom</button>
</div>
);
}
export default App;
八. 评论案例
javascript
import { useState, useRef } from 'react'
const list = [{
id: 1,
content:'sss'
}]
function App() {
const [commentList, setCommentList] = useState(list)
const [content, setValue] = useState('')
const inputRef = useRef(null)
const publish = () => {
if (!content.trim()) return
setCommentList([
...commentList,
{
id: Date.now(),
content: content
}
])
setValue('')
inputRef.current?.focus() // 加了安全调用
}
return (
<div>
<input
type='text'
value={content}
onChange={(e) => setValue(e.target.value)}
ref={inputRef}
/>
<button onClick={publish}>发表评论</button>
<div style={{ marginTop: 20 }}>
{commentList.map(item => (
<div key={item.id} style={{ padding: '8px 0' }}>
{item.content}
</div>
))}
</div>
</div>
)
}
export default App