React-01-开发环境及JSX
环境搭建
# 创建环境
npx create-react-app 项目名
npx create-react-app react-demo
项目跑起来试一下
yarn start
npm run start
package.json
## 核心依赖
"react": "^19.2.1",
"react-dom": "^19.2.1",
## 命令
"start": "react-scripts start",
只保留 App.js 、index.js
- index.js:项目的入口
// 1.项目入口文件
import ReactDOM from 'react-dom/client';
// 2.导入项目的根组件
import App from './App';
// 3.把APP根组件渲染到id为root的dom节点上,在 public/index.html 中
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<App />
);
l
index.js 要做的事,其实就是要将项目的根组件,以 react 的形式渲染到 public/index.html 中去
public/index.html当中关键代码
<div id="root"></div>
- App.js:项目根组件
// 项目根组件
// App.js 被加载到-> index.js 渲染到-> public/index.html(root)
function App() {
return (
<div className="App">
this is App
</div>
);
}
export default App;
JSX语法
概念:JSX 是 JavaScript 和 XML(HTML)的缩写,表示在 JS 代码中编写 HTML 模版结构,它是React中编写 UI 模版的方式
JSX中使用JS表达式
- 使用引号传递字符串
- 使用 JavaScript 变量
- 函数调用和方法调用
- 使用 JavaScript 对象
const a = 100;
function getMessage(a, b) {
return a + b;
}
function App() {
return (
<div className="App">
this is App
{/* 1. 使用引号传递字符串 */}
{"this is message"}
{/* 2. 使用 JavaScript 变量 */}
{a}
{/* 3. 函数调用和方法调用 */}
{getMessage(a, 111)}
{/* 4. 使用 JavaScript 对象 */}
<div style={{color: 'red'}}>
<p>这是一行文字</p>
</div>
</div>
);
}
JSX 实现列表渲染
如下:
<ul>
<li>张三</li>
<li>李四</li>
</ul>
渲染:
const list = [
{id: 1001, name: '张三'},
{id: 1002, name: '李四'},
{id: 1003, name: '王五'},
]
function App() {
return (
<div className="App">
<ul>
{/* 渲染列表 */}
{
list.map(item => <li key={item.id}>{item.name}</li>)
}
</ul>
</div>
);
}
条件渲染
const flag = true;
const caseType = 1
function getCaseType() {
if (caseType === 1) {
return <div>这是caseType为1的情况</div>
} else if (caseType === 2) {
return <div>这是caseType为2的情况</div>
}
}
function App() {
return (
<div className="App">
<ul>
{/* 条件渲染:方式一 */}
{flag ? <p>这是true</p> : <p>这是false</p>}
{/* 条件渲染:方式二 */}
{flag && <p>这是true</p>}
{/* 条件渲染:复杂方式 */}
{getCaseType()}
</ul>
</div>
);
}
事件绑定
语法:on + 事件名称 = { 事件处理程序 },整体上遵循驼峰命名法
const handleClick = () => {
console.log("点击了按钮");
};
function App() {
return (
<div className="App">
<button onClick={handleClick}>点击我</button>
</div>
);
}
获取事件
const handleClick = (e) => {
console.log("点击了按钮, 我拿到了事件对象", e);
};
function App() {
return (
<div className="App">
<button onClick={handleClick}>点击我</button>
</div>
);
}
自定义参数
const handleClick = (name) => {
console.log(`${name}点击了按钮`);
};
function App() {
return (
<div className="App">
<button onClick={() =>handleClick('张三')}>点击我</button>
</div>
);
}
即要参数,又要事件
const handleClick = (name, e) => {
console.log(`${name}点击了按钮,事件对象是`, e);
};
function App() {
return (
<div className="App">
<button onClick={(e) => handleClick("张三", e)}>点击我</button>
</div>
);
}
这几者的区别
| 对比维度 | 写法1:直接传递函数引用 | 写法2:箭头函数包裹 |
|---|---|---|
| 执行时机 | React 自动传递事件对象 | 自定义参数传递 |
| Java 类比 | 方法引用:::handleClid |
匿名 Lambda 表达式 e-> handleClick("张三") |
| 适用场景 | 只需时间对象,无需额外参数 | 需要传递自定义参数 |
React组件基础使用
组件初体验
概念:一个组件就是用户界面的一部分,它可以有自己的逻辑和外观,组件之间可以互相嵌套,也可以复用多次
在React中,一个组件就是首字母大写的函数,内部存放了组件的逻辑和视图UI, 渲染组件只需要把组件当成标签书写即可
// 定义组件
function Button() {
return <button>click me</button>;
}
function App() {
return (
<div className="App">
{/* 渲染组件 */}
<Button />
</div>
);
}
useState基础使用
useState 是一个 React Hook(函数),它允许我们向组件添加一个状态变量, 从而控制影响组件的渲染结果。
- 导包:
import { useState } from "react"; - 定义
useState钩子函数 - 在对应的地方触发函数并使用
import { useState } from "react";
function App() {
// 定义状态
const [count, setCount] = useState(0);
// 定义点击事件
const handleClick = () => {
setCount(count + 1);
};
return (
<div className="App">
{/* 点击按钮,count增加1 */}
<button onClick={handleClick}>{count}</button>
</div>
);
}
export default App;
useState的工作原理:
- 首次渲染
- 首次渲染:组件首次渲染时,
useState(0)被调用 - React创建一个状态单元,初始值为0
- 返回数组
[0, setCount],通过解构赋值给count和setCount - 组件使用 count 的值(0)渲染UI
- 首次渲染:组件首次渲染时,
- 状态更新
- 用户点击按钮,出发
handleClick函数 handleClick调用setCount(count + 1)- React将状态值更新为1
- React自动重新渲染组件
- 再次调用
useState(0)时,React会忽略初始值,直接更新后的状态[1, setCount]
- 用户点击按钮,出发
样式组件(css引入)
- 通过单行引入(省略)
- 通过对象引入
- 通过文件引入
css 样式文件
.foo {
color: blue;
font-size: 20px;
}
引入
import './index.css'
const spanStyle = {
color: "red",
fontSize: "20px",
};
function App() {
return (
<div className="App">
<span style={spanStyle}>通过对象引入样式</span>
<span className="foo">通过类名引入样式</span>
</div>
);
}
export default App;
评论功能demo
小工具
- lodash:hutool包
中文文档地址:https://www.lodashjs.com/
安装:
npm install lodash
使用示例:
import _ from "lodash";
// 使用示例
var users = [
{ 'user': 'fred', 'age': 48 },
{ 'user': 'barney', 'age': 34 },
{ 'user': 'fred', 'age': 40 },
{ 'user': 'barney', 'age': 36 }
];
// 以 `user` 升序排序 再 `age` 以降序排序。
_.orderBy(users, ['user', 'age'], ['asc', 'desc']);
// => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
- classnames 优化类名控制
Gitbub 官网:https://github.com/JedWatson/classnames
安装:
npm install classnames
使用示例:
const classNames = require('classnames');
classNames('foo', 'bar'); // => 'foo bar'
classNames('nav-item', {active: tabType === item.type})
- uuid
npm install uuid
使用示例:
import { v4 as uuidV4 } from 'uuid';
const uuid = uuidV4();
- Day.js:用来格式化日期
Day.js 官网:https://day.js.org/zh-CN/
npm install dayjs
# or
yarn add dayjs
# or
pnpm add dayjs
使用,格式地址:https://day.js.org/docs/zh-CN/display/format
const dayjs = require('dayjs')
//import dayjs from 'dayjs' // ES 2015
dayjs().format()
// 默认返回的是 ISO8601 格式字符串 '2020-04-02T08:02:17-05:00'
dayjs('2019-01-25').format('[YYYYescape] YYYY-MM-DDTHH:mm:ssZ[Z]')
// 'YYYYescape 2019-01-25T00:00:00-02:00Z'
dayjs('2019-01-25').format('DD/MM/YYYY') // '25/01/2019'
- json-server
npm install json-server -D # 开发环境中使用
yarn add json-server --dev
使用时可以配置到 package.json 中去
"server": "json-server db.json --port 3004"
- axios
npm i axios
表单双向绑定
受控表单绑定
表单的双向绑定
import { useState } from "react";
function App() {
// 1.声明react状态
const [inputValue, setInputValue] = useState("");
const logInputValue = () => {
console.log("当前输入框的值是:", inputValue);
};
return (
<div className="App">
{/* 2.绑定状态 */}
<input
type="text"
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
/>
<button onClick={logInputValue}>点我打印</button>
</div>
);
}
export default App;
获取DOM
- 使用
useRef创建ref对象,并与JSX绑定 - 在
DOM可用时,通过inputRef.current拿到DOM对象
import { useRef, useState } from "react";
function App() {
// 1.生成ref对象
const inputRef = useRef(null);
const showDom = () => {
// 3.拿到dom对象
console.log(inputRef.current);
console.dir(inputRef.current);
};
return (
<div className="App">
{/* 2.绑定到dom标签上 */}
<input ref={inputRef} />
<button onClick={handleButton}>点我一下</button>
</div>
);
}
export default App;
控制台输出
value: "1"
__reactEvents$3e1hf0x56ug: Set(1) {'invalid__bubble'}
__reactFiber$3e1hf0x56ug: FiberNode {tag: 5, key: null, elementType: 'input', type: 'input', stateNode: input, …}
__reactProps$3e1hf0x56ug: {ref: {…}}
_valueTracker: {getValue: ƒ, setValue: ƒ, stopTracking: ƒ}
accept: ""
accessKey: ""
align: ""
alt: ""
等等........
