https://www.yuque.com/fechaichai/qeamqf/xbai87 文档地址
Jsx 基础语法
1.识别常量
2.原生 js 方法调用
3.三元运算符(常用)
const name = '猜猜老师多少岁'
const getAge = () => 18
const flag = true
export default function App() {
return (
<div className="App">
{name}
{getAge()}
{flag ? '真棒' : '真菜'}
</div>
)
}
js 列表渲染
技术方案:map
注意事项:遍历列表时也需要一个类型为 number/string 不可重复 key 提高 diff 性能
key 仅仅在内部使用,不会出现在真实的 dom 结构中
const stu = [
{ id: 1, name: '张一' },
{ id: 2, name: '张二' },
{ id: 3, name: '张三' },
]
export default function App() {
return (
<div>
{stu.map((val) => (
<h1 key={val.id}>{val.name}</h1>
))}
</div>
)
}
条件判断
技术方案:三元表达式(常用) 逻辑&&运算(短路与运算)
const flag = true
export default function App() {
return (
<div>
{flag ? <span>this is span</span> : null}
{true && <span>this is span</span>}
</div>
)
}
多语句条件判断
有一个状态 type 1 2 3
1 —> h1
2 —> h2
3 —> h3
原则:模板中的逻辑尽量保持精简
复杂的多分支的逻辑 收敛为一个函数 通过专门的函数来写分支逻辑 模板中只负责调用
const getHag = (type) => {
switch (type) {
case 1:
return <h1>1</h1>
case 2:
return <h2>2</h2>
case 3:
return <h3>3</h3>
}
}
export default function App() {
return <div>{getHag(1)}</div>
}
jsx 样式控制
1.行内样式 - 在元素身上属性绑定一个 style 属性即可
2.类名样式 - 在元素身上属性绑定一个 className 属性即可
3.动态属性 - 使用三元运算符
import './App.css'
const flag = true
export default function App() {
return (
<div>
<h1 style={{ color: 'blue' }}>this is h1</h1>
<h2 className={flag ? 'active' : ''}>this is h2</h2>
</div>
)
}
注意事项
所有标签需要放到一个跟标签 可以换成<></>
所有标签都需要闭合
多个换行需要用括号
函数组件的创建与渲染
创建
function Hello() {
return <h1>你好</h1>
}
渲染 <
类式组件的创建与渲染
创建
class Hello extends React.Component {
render() {
return <h1>你是个啥</h1>
}
}
渲染 <
事件绑定
(函数组件)
export default function App() {
const show = () => {
console.log('函数组件被触发')
}
return (
<div>
<button onClick={show}>点我一下</button>
</div>
)
}
(类式组件)
import React, { Component } from 'react'
export default class App extends Component {
## 标准写法避免this的指向问题,这样写这样this指向就是当前组件的实例对象
show = () => {
console.log('类式组件被触发')
}
render() {
return (
<div>
<button onClick={this.show}>点我一下</button>
</div>
)
}
}
事件对象传递 e
export default function App() {
const show = (e) => {
console.log('函数组件被触发', e)
}
return (
<div>
<button onClick={show}>点我一下</button>
</div>
)
}
传递自定义参数
(1)方法一
export default function App() {
const show = (e) => {
console.log('函数组件被触发', e)
}
return (
<div>
<button onClick={show}>点我一下</button>
</div>
)
}
(2)方法二
export default function App() {
const show = (e, msg) => {
console.log('函数组件被触发', e)
}
return (
<div>
<button onClick={(e) => show(e, 'nihao')}>点我一下</button>
</div>
)
}
状态的定义与使用 state 注意不能使用赋值的手法修改 this.state.name=“tom” 错误
import React, { Component } from 'react'
export default class App extends Component {
## 定义状态
state = { name: 'jack' }
## 修改状态
changeName = () => {
this.setState({
name: 'tom',
})
}
render() {
return (
<div>
<h1>{this.state.name}</h1>
<button onClick={this.changeName}>点击修改名字</button>
</div>
)
}
}
受控组件 双向绑定
import React, { Component } from 'react'
export default class App extends Component {
## 定义状态
state = { name: 'jack' }
## 修改状态
changeName = (e) => {
this.setState(
{
name: e.target.value,
},
() => {
console.log(this.state.name)
}
)
}
render() {
return (
<div>
<input
type="text"
onChange={(e) => this.changeName(e)}
value={this.state.name}
/>
</div>
)
}
}
非受控组件 ref
1(采用 createRef 容器解决)
import React, { Component, createRef } from ‘react’
export default class App extends Component {
## 定义状态
state = { name: 'jack' }
## 修改状态
getName = () => {
console.log(this.myRef.current.value)
}
myRef = createRef()
render() {
return (
<div>
<input ref={this.myRef} type="text" onBlur={this.getName} />
</div>
)
}
}
组件通信
(父传子通信)
import React, { Component } from 'react'
export default class App extends Component {
state = { msg: '消息' }
render() {
return (
<div>
<SonF msg={this.state.msg} />
<SonC msg={this.state.msg} />
</div>
)
}
}
## 函数式子组件 结构 props 直接解构
function SonF({ msg }) {
## props是一个对象 里面存着通过父组件传入的所有数据
return (
<div>
<h1>我是函数组件,{msg}</h1>
</div>
)
}
## 类式子组件
class SonC extends Component {
render() {
## 这里要通过this这是固定写法
return (
<div>
<h1>我是类式组件,{this.props.msg}</h1>
</div>
)
}
}
(子传父通信)
import React, { Component } from 'react'
export default class App extends Component {
state = { sonDate: '父亲的数据' }
## 准备一个函数,传递给子组件
getSonMsg = (sonMsg) => {
return () => {
this.setState({
sonDate: sonMsg,
})
}
}
render() {
return (
<div>
<h1>{this.state.sonDate}</h1>
<Son getSonMsg={this.getSonMsg} />
</div>
)
}
}
function Son(props) {
const { getSonMsg } = props
return (
<div>
<button onClick={getSonMsg('我是子组件传递过来的数据')}>
点击更改父组件的state
</button>
</div>
)
}
(兄弟之间的通信) 子传父 父传子
跨组件传值 context
import React, { Component, createContext } from 'react'
## App ->A ->C
## App的数据直接交给C组件
## 1.导入createContext方法
## 注意事项上层组件和下层的组件的关系是相对的 通常我们会使用app作为数据的提供方
## 这里的语法都是固定的
const { Provider, Consumer } = createContext()
export default class App extends Component {
state = { sonDate: '父亲的数据' }
render() {
return (
<Provider value={this.state.sonDate}>
<div>
<A />
</div>
</Provider>
)
}
}
function A() {
return (
<div>
<h1>我是A组件</h1>
<C />
</div>
)
}
function C() {
return (
<div>
<h1>
我是c组件,接收到的数据是:
<Consumer>{(value) => <b>{value}</b>}</Consumer>
</h1>
</div>
)
}
props 的 children 属性
在组件的内部里面写了一个文本就会出现这个属性
import React from 'react'
export default class App extends React.Component {
state = { sonDate: '父亲的数据' }
render() {
return (
<div>
<Son>你好</Son>
</div>
)
}
}
function Son(props) {
return (
<div>
<h1>我是 A 组件:{props.children}</h1>
</div>
)
}
props 的校验
安装 prop-types 命令 npm add prop-types
(函数组件校验)
import PropTypes from 'prop-types'
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
<div>
<Son name="jack" age={18} sex="男" />
</div>
)
}
}
## 第二种设置默认值的方法,常用
function Son({ age = 20 }) {
return (
<div>
<h1>
我是子组件{props.name},{props.age},{props.sex}
</h1>
</div>
)
}
Son.propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
sex: PropTypes.string,
}
## 第一种设置默认值的方法
Son.defaultProps = {
age: 19,
sex: 'man',
}
(类式组件校验)
import PropTypes from 'prop-types'
import React, { Component } from 'react'
export default class App extends Component {
render() {
return (
<div>
<Son name="jack" sex="男" />
</div>
)
}
}
class Son extends Component {
## Son.propTypes = { =>可以换位static propTypes 挂载到类上面记住哦用static修饰的都是挂载类式上面
static propTypes = {
name: PropTypes.string.isRequired,
age: PropTypes.number,
sex: PropTypes.string,
}
static defaultProps = {
age: 19,
sex: 'man',
}
render() {
return (
<div>
<h1>
我是子组件{this.props.name},{this.props.age},{this.props.sex}
</h1>
</div>
)
}
}
组件的生命周期(只有类组件才有生命周期)
constructor(不常用了,基本不用了)
render (常用,更新和渲染都会调用,不能这里面调用 setState)
componentDidMount (常用 ajax,定时器)
componentDidUpdate(不常用,获取新 DOM,不能这里面调用 setState)
componentWillUnmount(常用,组件卸载前,清除定时器)
使用 antd 组件 记得如何使用 uuid 是需要调用方法的
1.安装 antd 输入命令 npm add antd
2.在 App.css 中引入 antd.css @import ‘~antd/dist/antd.css’;
3.在 App.js 目录中引入 App.css 就可以使用了(配合文档)
hook 函数
useState ## 1 导入 useState ## 2 执行这个函数并且传入初始值 ## 3 [数据,修改数据的方法]
import { useState } from 'react'
export default function App() {
const [count, setCount] = useState(0) ## 名字可以自定义,尽量语义化
return (
<div>
<button onClick={setCount(count + 1)}>点击我{count}</button>
</div>
)
}
useEffect
import { useState, useEffect } from 'react'
## 1 导入 useEffect
## 2 在函数组件中使用 并且传入回调 并且定义副作用
## 3 当我们修改状态更新组件时,副作用也会不断执行
## 依赖项控制副作用的执行时机
## 1.默认状态(无依赖项) useEffect(() => {函数体})
## 组件初始化的时候先执行一次 等到每次数据修改组件更新再次执行
## 2.添加一个空数组依赖项 useEffect(() => {函数体}, [])
## 组件初始化的时候执行一次以后就不执行了
## 3.依赖特定向 useEffect(() => {函数体}, [count])
## 组件初始一次 依赖特定向会发生变化
## 4.注意事项
## 只要在useEffect回调函数中用到的数据状态就应该出现在函数声明当中 否则可能会有bug
export default function App() {
const [count, setCount] = useState(0) ## 名字可以自定义,尽量语义化
useEffect(() => {
document.title = count
}, [count])
return (
<div>
<button onClick={() => setCount(count + 1)}>点击我{count}</button>
</div>
)
}
useState 传入函数
import { useState } from 'react'
export default function App() {
const [count, setCount] = useState(() => {
return 0
})
return (
<div>
<button onClick={() => setCount(count + 1)}>点击我{count}</button>
</div>
)
}
清除副作用 useEffect 在 useEffect 里面添加 return 返回一个函数里面写入清除的东西
import { useState, useEffect } from 'react'
export default function App() {
const [flag, setFlag] = useState(true)
return (
<div>
{flag ? <Son /> : null}
<button
onClick={() => {
setFlag(!flag)
}}>
点我清除组件
</button>
</div>
)
}
function Son() {
const [count, setCount] = useState(0)
useEffect(() => {
console.log('我是定时器')
const timer = setInterval(() => {
setCount(count + 1)
}, 1000)
return () => {
clearInterval(timer)
}
}, [count])
return <h1>{count}</h1>
}
useRef 获取 dom 与实例对象
import { useRef } from 'react'
export default function App() {
const input = useRef(null)
return (
<div>
<input
type="text"
ref={input}
onChange={() => {
console.log(input.current)
}}
/>
</div>
)
}
useContext
import { createContext, useContext } from 'react'
const Context = createContext()
export default function App() {
return (
<Context.Provider value={20}>
<A />
</Context.Provider>
)
}
function A() {
return (
<div>
我是组件A
<C />
</div>
)
}
function C() {
const value = useContext(Context)
return <div>我是组件C,从App组件哪里拿到的值是{value}</div>
}
路由 安装路由 npm add react-router-dom
案例 about home
import React from 'react'
## 进行路由配置
import { BrowserRouter, Link, Routes, Route } from 'react-router-dom'
export default function App() {
return (
## 声明一个非hash模式的路由
<BrowserRouter>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
</Routes>
</BrowserRouter>
)
}
function Home() {
return (
<div>
<h1>Home组件</h1>
</div>
)
}
function About() {
return (
<div>
<h1>About组件</h1>
</div>
)
}
(http:## localhost:3000/# /about)(http:## localhost:3000/about 推荐)
<Router path=“/path” element={}/>
编程式导航
import React from 'react'
## 进行路由配置
import {
BrowserRouter,
Link,
Routes,
Route,
useNavigate,
} from 'react-router-dom'
export default function App() {
return (
## 声明一个非hash模式的路由
<BrowserRouter>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
</Routes>
</BrowserRouter>
)
}
function Home() {
return (
<div>
<h1>Home组件</h1>
</div>
)
}
function About() {
return (
<div>
<h1>About组件</h1>
</div>
)
}
function Login() {
const navigate = useNavigate()
function goAbout() {
navigate('/about',{replace:true})
}
return <button onClick={goAbout}>点我跳转到about页面</button>
}
searchParams 传参
import React from 'react'
## 进行路由配置
import {
BrowserRouter,
Link,
Routes,
Route,
useNavigate,
useSearchParams,
} from 'react-router-dom'
export default function App() {
return (
## 声明一个非 hash 模式的路由
<BrowserRouter>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
</Routes>
</BrowserRouter>
)
}
function Home() {
return (
<div>
<h1>Home 组件</h1>
</div>
)
}
function About() {
const [params] = useSearchParams()
console.log(params.get('name'))
return (
<div>
<h1>
About 组件获取传递过来的 id 为{params.get('id')},名字为
{params.get('name')}
</h1>
</div>
)
}
function Login() {
const navigate = useNavigate()
function goAbout() {
navigate('/about?id=101&name=lizhen')
}
return <button onClick={goAbout}>点我跳转到 about 页面</button>
}
params 传参
import React from 'react'
## 进行路由配置
import {
BrowserRouter,
Link,
Routes,
Route,
useNavigate,
useParams,
} from 'react-router-dom'
export default function App() {
return (
## 声明一个非hash模式的路由
<BrowserRouter>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about/:id" element={<About />}></Route>
<Route path="/login" element={<Login />}></Route>
</Routes>
</BrowserRouter>
)
}
function Home() {
return (
<div>
<h1>Home组件</h1>
</div>
)
}
function About() {
const params = useParams()
return (
<div>
<h1>About组件获取传递过来的id为{params.id}</h1>
</div>
)
}
function Login() {
const navigate = useNavigate()
function goAbout() {
navigate('/about/102')
}
return <button onClick={goAbout}>点我跳转到about页面</button>
}
嵌套路由 注意 outLet 写到二级组件下面
import React from 'react'
## 进行路由配置
import { BrowserRouter, Link, Routes, Route, Outlet } from 'react-router-dom'
export default function App() {
return (
## 声明一个非hash模式的路由
<BrowserRouter>
<Link to="/">首页</Link>
<Link to="/about">关于</Link>
<Routes>
<Route path="/" element={<Home />}></Route>
<Route path="/about" element={<About />}>
{/* 定义二级嵌套路由 */}
<Route path="son" element={<Son />}></Route>
</Route>
</Routes>
</BrowserRouter>
)
}
function Home() {
return (
<div>
<h1>Home组件</h1>
</div>
)
}
function About() {
return (
<div>
<h1>About组件</h1>
<Outlet />
</div>
)
}
function Son() {
return <h1>我是嵌套在About组件的路由组件</h1>
}
默认二级路由
如何设置其为首页呢,直接把他的 path 换成 index 即可
<Route path="/about" element={<About />}>
{/* 定义二级嵌套路由 */}
<Route index element={<Son />}></Route>
</Route>
404 页面放在路由最后
## 当所有路径都没有匹配时,显示
<Route path="*" element={<NotFound />}></Route>
mobx 这个就是何 redux 一样的一个东西
实现第一 store 应用
App.js 里面的代码
import { observer } from 'mobx-react-lite'
import React from 'react'
## 1.导入counterStore
## 2.导入中间件连接mobx react 完成响应式
import counterStore from './store/counter'
function App() {
return (
<div>
{/* 把store中的count渲染一下 */}
{counterStore.count}
{/* 点击事件触发action函数修改count值 */}
<button onClick={counterStore.addCount}>+</button>
</div>
)
}
export default observer(App)
store/counter.js 里面的代码
import { makeAutoObservable } from 'mobx'
## 编写第一个mobx store小案例
class CounterStore {
## 1.定义数据
count = 0
constructor() {
## 2.把数据弄成响应式
makeAutoObservable(this)
}
## 3.定义一个action函数(修改数据)
addCount = () => {
this.count++
}
}
## 4.实例化然后导出给react使用
const counterStore = new CounterStore()
export default counterStore
mobx-computed 属性
store/counter.js 里面的代码
import { makeAutoObservable } from “mobx”
编写第一个 mobx store 小案例
class CounterStore {
list = [0, 1, 2, 3, 4, 5]
constructor() {
2.把数据弄成响应式
makeAutoObservable(this)
}
定义计算属性
get filterList () {
return this.list.filter(item => item > 2)
}
addList = () => {
this.list.push(7, 9, 8)
}
}
4.实例化然后导出给 react 使用
const counterStore = new CounterStore()
export default counterStore
App.js 里面的代码
import { observer } from 'mobx-react-lite'
import React from 'react'
import counterStore from './store/counter'
function App() {
return (
<h1>
{counterStore.filterList}
<button onClick={counterStore.addList}>点击添加数字</button>
</h1>
)
}
export default observer(App)
mobx 模块化 流程分别创建对应的 store 文件,汇总到 store/index.js 文件下
counter.Store.js
import { makeAutoObservable } from 'mobx'
class CounterStore {
count = 0
constructor() {
makeAutoObservable(this)
}
addCount = () => {
this.count++
}
}
const counterStore = new CounterStore()
export default counterStore
store/list.Store.js
import { makeAutoObservable } from 'mobx'
class ListStore {
list = [0, 1, 2, 3, 4, 5]
constructor() {
makeAutoObservable(this)
}
get filterList() {
return this.list.filter((item) => item > 2)
}
addList = () => {
this.list.push(7, 9, 8)
}
}
const listStore = new ListStore()
export default listStore
store/index.js
import React from 'react'
import counterStore from './counter.Store'
import listStore from './list.Store'
class RootStore {
constructor() {
this.counterStore = counterStore
this.listStore = listStore
}
}
const rootStore = new RootStore()
const context = React.createContext(rootStore)
const useStore = () => React.useContext(context)
export default useStore
App.js
import { observer } from 'mobx-react-lite'
import useStore from './store'
function App() {
const usestore = useStore()
return (
<div>
{usestore.counterStore.count}
<button onClick={usestore.counterStore.addCount}>点击添加数字</button>
</div>
)
}
export default observer(App)