初始react
快速上手
快速搭建开发环境
- create-react-app 是一个快速 创建React开发环境的工具,底层由Webpack构建,封装了配置细节,开箱即用
- 执行命令:npx create-react-app react-basic
- npx node.js工具命令,查找并执行后续的包命令
- create-react-app 核心包(固定写法),用于创建React项目
- react-basic React项目的名称(自定义)
JSX
- 概念:JSX是JavaScript 和 XML 的缩写,表示在JS代码中编写HTML模板结构,它是React中编写UI模板的方式
- 优势:Html的声明式模板写法;js的可编程能力
- 本质:jsx并不是标准的js语法,它是js的语法扩展,浏览器本身不能识别,需要通过解析工具做解析之后才能识别
在JSX中使用JS表达式
- 在jsx中可以通过大括号语法 {} 识别JavaScript中的表达式,比如常见的变量,函数调用,方法调用等等
- 使用引号传递字符串
- 使用JavaScript变量
- 函数调用和方法调用
- 使用JavaScript对象
- 注意:if,switch,变量声明语句不能出现在{}中
jsx实现条件渲染
-
使用逻辑与运算符 &&,三元表达式(?😃 实现基础的条件渲染
-
使用if-else语句实现条件渲染
{ flag && <span>this is a span</span>};
const ifLogin = function (flag) {
if(flag){
return <span>登录成功!</span>
}
else{
return <span>未登录</span>
}
}
传递自定义参数
- 语法:事件绑定的位置改造成箭头函数的写法,在执行clickHander实际处理业务函数的时候传递实参。
function App() {
const clickHandler = (name) => {
console.log('button按钮点击了', name);
}
return <button onClick={() => clickHandler('jack')}>click me</button>
}
同时传递事件对象和自定义参数
- 语法:在事件绑定的位置传递事件实参e和自定义参数,click Handler中声明形参,注意顺序对应
function App() {
const clickHandler = (name,e) => {
console.log("button按钮点击了",name,e);
}
return <button onClick = {(e) => clickHandler('jack',e)}> click me </button>
}
React组件
- 在react中,一个组件就是首字母大写的函数,内部存放了组件的逻辑和视图UI,渲染组件只需要把组件当成标签书写即可
function Button () {
return <button> click me </button>}
useState基础使用
useState 是一个 React Hook (函数),它允许我们向组件添加一个状态变量,从而控制影响组件的渲染结果。
本质:和普通JS变量不同的是,状态变量一旦发生变化组件的视图UI也会跟着变化 (数据驱动视图)
const [count, setCount] = useState(0);
- useState是一个函数,返回值是一个数组
- 数组中的第一个参数是状态变量,第二个参数是set函数用来修改状态变量
- useState的参数将作为count的初始值
- 计数器案例:
// 实现计数器
import {useState} from 'react';
function App() {
const [count,setCount] = useState(0);
// 修改count变量
const handlerClick = () => {
setCount(count + 1);
}
return (
<div className="App">
<button onClick={handlerClick}>{count}</button>
</div>
);
}
export default App;
修改对象状态
规则: 对于对象类型的状态变量,应该始终传给set方法一个全新的对象进行修改
const [form,setForm] = useState({
name: 'jack'
})
// 直接修改原对象,不引发视图变化
const handleChangeName = () => {
form.name = 'jhon'
}
// 调用set传入新对象用于修改
const handleChangeName = () => {
setForm({
// 使用展开运算符,将form对象的属性一一展开
...form,
// 若添加的属性与展开的属性一致,直接替换
name: "john"
})
}
classNames优化类名控制
className是一个简单的JS库,可以方便的通过条件动态控制class类名的显示
className = {classNames('nav-item',{active: type===item.type})}
//active - 动态类名key表示要控制的类名,
//value _ 表示条件,true的时候类名显示
受控表单绑定
概念:使用React组件的状态(usestate) 控制表单的状态 - (类似于vue中的v-model)
- 准备一个React状态值
- 通过value属性绑定状态,通过onChange属性绑定状态同步的函数
<input
type = "text"
value = {value}
onChange={(e) => setValue(e.target.value)}
/>
在react中获取dom
在react组件中获取/操作 DOM,需要使用useRef钩子函数,分为两步
- 使用useRef创建ref对象,并与jsx绑定
- 在dom可用时,通过inputRef.current拿到DOM对象
const inputRef = useRef(null);
<input type='text' ref={inputRef}></input>
console.log(inputRef.current)
react语法深入
组件通信
概念:组件通信就是组件之间的数据传递,根据组件嵌套关系的不同,有不同的通信方法
父子通信
-
实现步骤:
- 父组件传递数据 - 在子组件标签上绑定属性
- 子组件接收数据 - 子组件通过props参数接收数据
父传子 - props说明
- props可传递任意的数据:数字,字符串,布尔值,数组,对象,函数,jsx
- props是只读对象: 子组件只能读取props中的数据,不能直接进行修改,父组件的数据只能由父组件修改
父传子 - 特殊的prop children
- 场景:当我们把内容嵌套在子组件标签中时,父组件会自动在名为children的prop属性中接收该内容
子传父
- 核心思路:在子组件中调用父组件的函数并传递参数
兄弟组件通信 - 使用状态提升
- 实现思路:借助 “状态提升”机制,通过父组件进行兄弟组件间的数据传递
使用Context机制跨层级组件通信
- 实现步骤
- 使用createContext方法创建一个上下文对象Ctx
- 在顶层组件 (App) 中通过Ctx.Provider 组件提供数据
- 在底层组件 (B) 中通过useContext 钩子函数获取消费数据
useEffect
- 概念:useEffect是一个 React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作,比如发送AJAX请求,更改DOM等等
- 说明:上面组件中没有发生任何的用户事件,组件渲染完毕之后就需要和服务器要数据,整个过程属于 “只由渲染引起的操作”
- 语法:
useEffect(() => { }, [])
// 参数1是一个函数,可以把它叫做副作用函数,在函数内部可以放置要执行的操作
// 参数2是一个数组(可选参),在数组里放置依赖项,不同依赖项会影响第一个参数函数的执行,当是一个空数组的时候,副作用函数只会在组件渲染完毕之后执行一次
useEffect 依赖项参数说明
- useEffect副作用函数的执行时机存在多种情况,根据传入依赖项的不同,会有不同的执行表现
useEffect - 清除副作用
- 在useEffect中编写的由渲染本身引起的对接组件外部的操作,社区也经常把它叫做副作用操作,比如在useEffect中开启了一个定时器,我们想在组件卸载时把这个定时器再清理掉,这个过程就是清理副作用
- 说明:清除副作用的函数最常见的执行时机是在组件卸载时自动执行
自定义Hook函数
- 自定义Hook是以use打头的函数,通过自定义Hook可以用来实现逻辑的封装和复用
- 封装自定义Hook函数通用思路
ReactHooks使用规则
- 只能在组件中或者其它自定义Hook函数中调用
- 只能在组件的顶层调用,不能嵌套在if,for,其它函数中,例如:
- json-server: 一个快速以.json文件作为数据源模拟接口服务的工具