react基础笔记

211 阅读18分钟

初识 react

  1. 导入react文件
     <!-- react  核心文件   暴露一个  React 对象 -->
    <script src="./js/react.development.js"></script>
    <!-- react 操作dom 的文件  暴露一个  ReactDOM 对象 -->
    <script src="./js/react-dom.development.js"></script>

  1. 创建容器
 <div id="root"></div>

  1. 创建 react 元素
let vdom = React.createElement("h1",{title:"初识react"},"hello world!"); 
  1. 将创建好的react元素展示到 容器中
ReactDOM.render(vdom,document.getElementById("root"));

createElement 参数

第一个 参数 标签名 第二个参数 标签的属性 {title:"初识 react"} / null 从第三个参数开始 全部都是 标签体的内容

dom

真实dom 直接在html文件中写好的。

虚拟dom 通过 React.createElememt() 所创建的

区别: 虚拟dom比较轻。属性比较少。

jsx

在 js 中 更高效的写html标签 浏览器不会识别 jsx 语法。 babel 可以将 jsx 语法 转换为 js 语法。

JSX 注意

    1. 不能用引号包裹,可以用 (小括号) 包裹
    2. JSXjs  拼接时,需使用 {}  表达式
    3. JSX 设置 class 时,须使用 className
    4. JSX 设置 style 时,须使用 {{color:"red",textAlign:"center",fontSize:"30px"}}   形式, css样式 多单词 须使用 小驼峰形式
    5. JSX 必须要有根标签
    6. JSX 中的单标签必须闭合,  例: <img/> <hr/> <br/> <input/> 等,或者<img><img/>形式
    7. JSX 中的标签名
        (1) 小写字母开头,则到HTML中找对应的标签,找到则创建,找不到则报错;
        (2) 大写字母开头,则到React中找对用的组件,找到则创建,找不到则报错;
        (3) 如果编写的html标签,则标签名首字母[一定要小写];如果编写的时React组件,则标签名首字母[一定要大写]

jsx 中的表达式

  1. 字面量数据 string number array function 有意义 boolean undefined null Symbol 没有意义 object 会报错
  2. 变量
  3. 方法调用
  4. 逻辑运算符 &&
  5. react 元素虚拟dom对象

jsx 条件渲染

  1. if else
  2. 三元运算符
  3. 逻辑运算符 &&

js中的循环

  1. for 已知条件,已知范围
  2. while 未知条件,未知范围
  3. do while 至少执行一次
  4. for of 循环遍历数据
  5. for in 循环遍历对象
  6. forEach 循环遍历数组,数组一个方法
  7. map 循环遍历数组,数组一个方法,返回一个新数组

diff 算法 以及 key

diffing react内置的算法:高效的 更新虚拟dom key 为虚拟dom添加唯一标识符 id 时间戳

js 事件

js是一个事件驱动的语言 事件必须调用函数 事件: onclick
onmouseover onmouseout onchange onblur onfocus keyUp keyDown

为元素绑定事件

1.
 document.getElementById("btn").onclick = function(){

}

2.
document.getElementById("btn").addEventListener("click",function(){

})

3.
 <button id="btn"  onclick="alert(123)">点击</button>

react中的事件

  1. react中的事件 必须使用小驼峰
  2. 事件必须调用函数
  3. 事件中的this 指向 undefined
  4. 阻止默认行为只能用 e.preventDefault();
  5. onChange事件 文本框值发生变化立即触发

默认行为

  1. 点击 a 链接会跳转
  2. 点击 submit 按钮会提交表单
  3. 鼠标右键 会显示菜单
  4. ctrl+c 复制

组件

传统封装 : js 函数 类 模块化 组件: html + css + js 封装 组件本质:就是自定义标签

react 中的组件

  1. 函数式组件 (1) 组件名称 必须首字母大写,返回虚拟dom (2) 组件以标签的形式在使用 (3) 组件名称见名知义 (4) 使用组件, 会在当前页面中去找 对应的这个 函数 ,调用执行函数,然后返回虚拟dom对象

  2. 类式组件 (1) 组件名称 必须首字母大写,返回虚拟dom (2) 组件以标签的形式在使用 (3) 组件名称见名知义 (4) 使用组件, 会在当前页面中去找 对应的这个 类,然后自动实例化对象,会自动调用render方法 ,然后返回虚拟dom对象

如何改变this指向

  1. call
  2. bind
  3. apply
  4. new 关键字: 创建了一个 空对象,并将this指向到这个对象

js 默认继承

原型继承 构造函数 类

nrm

  1. 安装 nrm 管理 npm 的资源的下载地址 npm i -g nrm
  2. 查看所有的npm 的下载的资源地址 nrm ls
  3. 配置 npm 镜像 nrm use taobao

安装react脚手架环境

  1. 下载安装环境 npm i create-react-app -g
  2. 创建项目 create-react-app 项目名(不能写汉字,不能有大写)
  3. 进入项目目录 cd hello-react
  4. 启动项目 npm start

git

将 项目 git 管理起来

  1. git init 初始化
  2. git add . 提交全部文件到 缓存区
  3. git commit -m "项目初始化"

vscode安装 git 可视化插件
Git Graph

react 脚手架目录结构

node_modules   依赖包目录
public      静态资源文件(网站根目录)
      index.html   webpack最终打包的模板文件
src         源代码目录  
      index.js  项目的入口文件
.gitignore  git忽略文件
package.json   项目的说明配置文件
package-lock.json   项目依赖包的锁文件

图片

  1. 位图 jpg png gif 图片内容比较丰富,缩放会失真。
  2. 矢量图 svg 图片内容比较单调,缩放不会失真。网站logo,导航图标

react 版本

目前: 最新版 18.2.0 react 最重要的版本 16.8, 16.8 之前官方推荐我们使用 类式组件 16.8 之后官方推荐我们使用 函数式组件 + hooks

安装 17:npm i react@17 react-dom@17

App 根组件

作用: 用来展示所有的组件

react 中的样式

外部样式 都是全局样式

  1. 解决样式作用域: less scss sass

组件三大属性之一 state

state 状态 存储数据 state 值 一般为js对象

state 中存储哪些数据:

  1. 后台传递的数据
  2. 前台通过表单收集到的用户的数据

组件中的 虚拟DOM 中的this 指向 当前的组件对象(实例对象)

react 中的事件回调里 的 this 指向 undefined

state 中的数据不能直接去更新 必须使用 this.setState() 更新 state中的数据。

vscode 插件

  1. Reactjs code snippets 快捷键: rcc 创建类式组件
  2. Auto Rename Tag
  3. Auto Close Tag

render 执行了几次?

render 渲染 将虚拟dom转换为真实dom 1 + n 次

组件

  1. components 一般(功能)组件
  2. pages 页面(路由)组件

组件数据

数据在哪,就只能在对应的组件中去更新数据

类式组件的三大属性之一 props

作用:接受父组件传递的数据 特点:

  1. props 数据是只读的,不能修改

    //在父组件中传递数据
    <Middle>{this.state.middleArr}</Middle>
    //在子组件中接受数据
    this.props.children

    //缺点:每次只能传递一个数据
    //children  存放组件标签体中的内容
    
    //在父组件中传递数据
     <Middle middleArr={this.state.middleArr} str={this.state.str} num={this.state.num} showPosition={this.showPosition}></Middle>

    <Middle  {...this.state}></Middle>
    //在子组件中接受数据
     let {middleArr,str,num} = this.props

     //优点: 传递数据的个数不限

props 数据验证

  1. 导入 props-types 包 import PropsType from "props-types"

  2. 在类中 创建 静态属性

//数据类型: string、boolean、number、object、array、func还有element(react元素)
static propTypes = {
        middleArr:PropsType.array.isRequired,
        str:PropsType.string.isRequired,
        num:PropsType.number.isRequired,
        showPosition:PropsType.func.isRequired
}

//指定默认数据
    static defaultProps = {
        str:"默认数据"
    }


组件(实例对象)三大属性

  1. state 状态 存储组件中的所有数据:后台传递的,前端表单收集的。
  2. props 接受外部组件传递的数据(字面量数据、方法)
  3. ref 获取真实 DOM 对象

组件的三大属性之一 ref

作用: 获取真实 DOM 对象

  1. 字符串形式 ref
    
    <div>
        <h1> 字符串形式的 ref </h1>
    
        <input type="text"  ref="username"  />
        <button ref="btn"   onClick={this.getdata} >点击获取数据</button>
        <div ref="div"  style={{width:300,height:300,border:"1px solid red"}}></div>
    </div>
    
    
    //获取数据
    getdata = ()=>{
       console.dir(this.refs.username.value);
       //获取输入框值
       let value = this.refs.username.value;
       //设置div内容
       this.refs.div.innerHTML = value;
    
       //清空输入框内容值
       this.refs.username.value = "";
    }
    
    



2. 回调函数形式的ref
``` jsx
     <h1> 回调函数形式的 ref </h1>
    {/* react 执行时,会将 当前的真实dom对象作为参数 执行 回调函数 */}
    <input type="text"  ref={  (el)=>{this.username = el}   }  />
    <button   onClick={this.getdata} >点击获取数据</button>
    <div  ref={ el => this.div = el   }   style={{width:300,height:300,border:"1px solid red"}}></div>



    //获取数据
    getdata = ()=>{
        //   console.log(this);
        //获取输入框值
        let value = this.username.value;
        //设置值
        this.div.innerHTML = value;
        //清空数据
        this.username.value = "";
    }

  1. 使用 createRef() 创建 ref 容器
    // 1. 使用 React.createRef()  创建ref容器,将ref容器注册到当前的实例对象属性
    username = React.createRef();
    div = React.createRef();

    
    {/* 2.使用 ref容器 */}
    <input type="text" ref={this.username} />
    <button   onClick={this.getdata} >点击获取数据</button>
    <div ref={this.div} style={{width:300,height:300,border:"1px solid red"}}></div>


    //获取数据
    getdata = ()=>{
       console.log(this.username.current.value);

       //获取数据
       let value = this.username.current.value;
       //设置数据
       this.div.current.innerHTML = value;
       //清空数据
       this.username.current.value = "";

    }


vscode 插件

Template String Converter

非受控组件

表单中的的数据通过 ref 形式获取到,并没有被state所管理。

受控组件

表单中的的数据 被 state 所管理。

高阶函数

  1. 构造函数
  2. 工厂函数

特点: 其实就是一个函数,接受一些函数类型的参数 或者 返回一个函数

  1. 接受函数类型的参数: Promise then catch setTimeout setInterval 数组一些方法(map forEach filter every )
  2. 返回一个函数 : 闭包 bind

html input type

html4: text password radio checkbox button submit reset image html5: url email number range search date week time datetime-local color tel

组件的生命周期

概念: 组件从创建 到 销毁的一系列过程 就叫组件的生命周期 在这个过程中,会自动调用一些函数,这些函数 就叫生命周期钩子函数

  1. componentDidMount 组件完成渲染【挂载】时调用 做组件初始化的工作 创建定时器 发送ajax请求 订阅消息 操作 DOM

  2. componentDidUpdate 组件完成更新时调用 操作 DOM

  3. componentWillUnmount 组件将要卸载时调用 做组件收尾的工作 销毁定时器 取消订阅

  4. render 渲染虚拟DOM 执行次数 1 + n

moment 获取日期库

  1. 下载安装 npm install moment --save --force
  2. 导入使用 import moment from "moment"
  3. 使用 moment().format("YYYY-MM-DD HH:mm:ss");

函数式组件 + hooks

hook 本质就是函数 rfc 快速创建函数式组件

注意:

  1. 只在最顶层使用 Hook,不要在条件或循环中
  2. 只在React组件函数内部中调用 Hook, 不要在组件函数外部调用

useState

作用:在函数式组件中创建状态

vscode react 插件

ES7+ React/Redux/React-Native snippets rfc 快速创建 函数式组件

useRef

作用: 获取真实DOM对象

useEffect

作用: 在函数式组件中模拟 生命周期钩子函数

 //1. 相当于  模拟  componentDidMount  和 componentDidUpdate
    useEffect(()=>{
        console.log("相当于  模拟  componentDidMount  和 componentDidUpdate");
    });

    // 2. useEffect  可以多次使用  模拟  componentDidMount  和 componentDidUpdate
    useEffect(()=>{
        console.log("执行了多次");
    })

    // 3. 单独模拟  componentDidMount 
    useEffect(()=>{
        console.log("单独模拟  componentDidMount ");
    },[]);

    //监听某个状态的变化,然后执行componentDidUpdate
    useEffect(()=>{
        console.log("单独模拟  componentDidMount ");
    },[count]); //  []  可以写状态,作用:监听哪个状态发生变化,然后执行componentDidUpdate


    // 4.   模拟 componentWillUnmount
    useEffect(()=>{
        return ()=>{
            console.log("模拟 componentWillUnmount");
        }
    },[]);

组件三大属性

  1. 类式组件 state 存储状态 props 获取外部组件传递的数据 ref 获取真实DOM对象
  2. 函数式组件 useState 存储状态 useRef 获取真实DOM对象 props 获取外部组件传递的数据

todolist

  1. 创建及 分拆组件
  2. 分析数据 状态的存储位置 todolist
  3. 状态 [ {id:1,title:"事件名称",done:false}, {id:2,title:"事件名称",done:false}, {id:3,title:"事件名称",done:false}, {id:4,title:"事件名称",done:false}, {id:5,title:"事件名称",done:false} ]

todolist 列表展示

  1. 在todolist 组件中创建 状态 数据
  2. 在 todolist 传递数据
     <TodoMain todolist={todolist} />
  1. 在 TodoMain 通过 props 接受外部组件传递的数据
    //解构赋值 获取props 数据
    let {todolist} = props;

    return (
        <ul className="todo-main">
          {
            todolist.map(item=>{
              return <TodoItem  item={item}  key={item.id}></TodoItem>
            })
          }
        </ul>
    )
}

  1. 在 TodoItem 通过 props 接受外部组件传递的数据

    //解构赋值获取item
    let {item} = props;

    return (
      <li>
          <label>
              <input type="checkbox"  checked={item.done} />
              <span>{item.title}</span>
          </label>
          <button className="btn btn-danger" style={{display:"none"}}>删除</button>
      </li>
    )

todolist 新增一个数据

  1. 在 todoHeader 将 input 绑定value值,并且绑定 onChange事件。作为一个 受控组件
  2. 在 todoHeader 为 input 绑定 onKeyUp 事件,获取 用户的 回车键。
  3. 在 todolist 组件中创建 addTodo 方法,为 state中的todolist数据 添加一个新的数据
  4. 在 todolist 组件中 使用 useEffect 测试 addTodo 方法
  5. 在 todolist 组件中 将 addTodo 方法传递给 todoHeader 组件
  6. 在 todoHeader 通过 props 接受 方法
  7. 在 keyup 中使用 addTodo 并传递参数

todolist 更新某个todo完成

  1. 在 todoItem 组件中 给 inpout 绑定 onChange事件,并传递 id 参数
  2. 在 todolist 组件中 创建 updateTodo ,循环遍历 todolist原始数据,判断当前传递的id的值是否和遍历的id一致,一致更新对应的todo 的 done值,会得到一个新数组,使用 setTodolist更新数据
  3. 在 todolist 组件中 将 updateTodo 传递给 todoMain组件
  4. 在 todoMain 组件中 通过 props 接受 updateTodo
  5. 在 todoMain 组件中 将 updateTodo 传递给 todoItem组件
  6. 在 todoItem 组件中 通过 props 接受 updateTodo
  7. 在 todoItem 组件中 使用 updateTodo,传递 id 和 done

nanoid

作用:一个小巧、安全、URL友好、唯一的 JavaScript 字符串ID生成器。 安装:npm i nanoid --force 导入: import { nanoid } from 'nanoid' 使用: nanoid()

前后台数据通信

  1. 原生js XMLHttpRequest
  2. jquery ajax()
  3. react
  4. axios 基于 Promise 前后台都可以使用
  5. fetch es6+

axios 请求方式

  1. get 获取数据 axios.get("URL地址",{params:{})

  2. post 新增数据 axios.post("URL地址",{json数据});

  3. put 全部更新数据 axios.put("url地址",{json数据});

  4. patch 局部更新数据 axios.patch("url地址",{json数据});

  5. delete 删除数据 axios.delete("url地址?id=xxx");

Fragment

react 中的内置组件 作用: 包裹 内部多个虚拟dom 优点: 浏览器不会渲染 Fragment 组件 简写形式: <></>

axios

安装 npm i axios --force 导入 import axios from "axios"

useEffect

useEffect 第一函数类型的参数 不能是异步函数

json-server

作用: 快速搭建后台服务 安装: npm i -g json-server 启动: json-server --watch db.json --port 8888

nprogress

  1. 安装 npm i nprogress --force
  2. 导入 import NProgress from "nprogress" import "nprogress/nprogress.css"
  3. 使用 NProgress.start(); NProgress.done();

then

返回的 Promise 对象

Promise

  1. 如果 返回的 一个非 Promise 值, Promise 【成功】
  2. 如果 返回的 一个 Promise 值,且 状态为成功, Promise 【成功】
  3. 如果 返回的 一个 Promise 值,且 状态为失败, Promise 【失败】

hooks

  1. useState
  2. useRef
  3. useEffect
  4. useContext 隔代组件数据传递

组件间的数据传递

  1. props 接受父组件传递的数据
  2. useContext 隔代组件数据传递
  3. pubsub-js 发布 订阅 机制 任意组件数据传递
  4. 路由 (1) URL地址栏 params传参 useParams()接受 特点: url地址比较优雅,会显示数据 heroscon/1/张飞,换个浏览器数据不会丢失 (2) URL地址栏 query 传参 useSearchParams() 接受 特点: url地址不优雅,会显示数据 heroscon?id=1&name=张飞,换个浏览器数据不会丢失 (3) state 传参 useLocation()接受 特点: url地址比较优雅,不会显示数据,数据保存在history状态中, 换个浏览器数据会丢失

react 内置的组件

  1. React.Fragment <></> 在浏览器中不加载
  2. countContext.Provider

pubsub-js

作用:发布 订阅 机制 任意组件数据传递

  1. 安装:npm i pubsub-js --force

  2. 导入 import PubSub from 'pubsub-js'

  3. publish() 发布
    publish("数据名称",要发布的数据)

  4. subscribe() 订阅

    PubSub.subscribe("要订阅的消息名称",(订阅的消息名称,订阅的数据)=>{});

  5. unsubscribe() 取消订阅

    在 组件将要卸载时 取消订阅 PubSub.unsubscribe(要取消的消息名称);

SPA 单页面应用

特点:加载数据少,速度快,不会出现页面空白

路由

作用:解决react 单页面应用 key => value
key: url路径名 value: 组件

react-router-dom

作用:在react 中操作网页路由 版本:React Router 6

  1. 安装 npm i react-router-dom --force
  2. 在 App.jsx 导入 import {BrowserRouter,Routes,Route} from "react-router-dom"

react-router-dom 组件

  1. 包裹所有的路由组件,最外层的路由组件
  2. 包裹所有的单个路由组件
  3. 加载单个路由组件
  4. 链接
  5. 导航链接
  6. 二级路由对应的组件占位
  7. 跳转组件

组件

  1. 一般组件 存在 components 使用形式:

  2. 路由组件 存在 pages 使用形式:<Route path="/duanzi" element={ } />

前端验证

用户在网页中所输入的所有数据都是非法的,必须经过验证。

路由中的 hook

  1. useRoutes() 创建路由对象
  2. useParams() 接受地址栏中的 params 参数
  3. useSearchParams() 接受地址栏中的 query 参数
  4. useLocation() 接受 路由传递的 state 数据
  5. useNavigate() 编程式路由,返回一个函数 navigate()

路由对象

{ path:"url地址", element:组件 children:子路由 index:入口 meta:{ 路由元信息

}

}

练习一

  1. 当地址栏 路由 是 heors ,展示英雄列表组件
  2. 当地址栏 路由 是 heorscon/1 ,展示英雄详情组件
    在 路由配置文件中 :
    {
        path:"/heroscon/:id/:name",
        element:<HerosCon/>,
        meta:{
            title:"英雄详情",
            isShow:false
        }
    }

    在 英雄列表组件中
    heros.map(item =>{
                        return (
                            <Link key={item.id} to={`/heroscon/${item.id}`}>
                                <li >
                                    <img src={ item.image && `http://cdn.xiaohigh.com${item.image}`}alt="" />
                                    <h3>{item.name}</h3>
                                </li>
                            </Link>
                        )
                    })


    在 英雄详情组件中
    //useParams()  接受url地址栏中的 params 参数
    let {id} = useParams();
    // console.log(obj);

    特点:  路由配置  设置的参数 ,使用时,必须对应

练习二

  1. 当地址栏 路由 是 heors ,展示英雄列表组件
  2. 当地址栏 路由 是 heorscon?id=1&name="张飞" ,展示英雄详情组件
    在路由配置中
    {
        path:"/heroscon",
        element:<HerosCon/>,
        meta:{
            title:"英雄详情",
            isShow:false
        }
    },


    在英雄列表组件中
     <Link key={item.id} to={`/heroscon?id=${item.id}&name=${item.name}`}>
                            <li >
                                <img src={ item.image && `http://cdn.xiaohigh.com${item.image}`}alt="" />
                                <h3>{item.name}</h3>
                            </li>
    </Link> 

    在 英雄详情组件中
    // 接受url地址栏中的 query 参数
    let [keyword,setKeyword] = useSearchParams();
    // console.log(keyword);
    let id = keyword.get("id");
    // console.log(id);

    特点:  灵活


练习三

  1. 当地址栏 路由 是 heors ,展示英雄列表组件
  2. 当地址栏 路由 是 heorscon ,展示英雄详情组件 state
 在路由配置中
    {
        path:"/heroscon",
        element:<HerosCon/>,
        meta:{
            title:"英雄详情",
            isShow:false
        }
    },

     在英雄列表组件中
     <Link key={item.id} to="/heroscon" state={{id:item.id,name:item.name}}>
                            <li >
                                <img src={ item.image && `http://cdn.xiaohigh.com${item.image}`}alt="" />
                                <h3>{item.name}</h3>
                            </li>
                        </Link>


在 英雄详情组件中
 //接受   路由传递的  state 数据
    let location = useLocation();
    // console.log(obj)

    let {id,name} = location.state;

    特点:  地址栏中不显示 传递的数据   state数据保存在 浏览器的 history 对象中

路由懒加载

  1. 导入 import { lazy, Suspense } from "react";
  2. 导入组件
// 首页 登录 注册  404 不需要懒加载
import Home from "../pages/Home/Home";
import NotFound from "../pages/NotFound/NotFound";
//懒加载
let Ref = lazy(()=> import("../pages/Ref/Ref"));
let Hooks = lazy(()=> import("../pages/Hooks/Hooks"));
let TodoList = lazy(()=> import("../pages/TodoList/TodoList"));
let Heros = lazy(()=> import("../pages/Heros/Heros"));
let Duanzi = lazy(()=> import("../pages/Duanzi/Duanzi"));
let News = lazy(()=> import("../pages/News/News"));
let Guonei = lazy(()=> import("../pages/News/Guonei"));
let Junshi = lazy(()=> import("../pages/News/Junshi"));
let HerosCon = lazy(()=> import("../pages/HerosCon/HerosCon"));
  1. 调用懒加载组件
{
        path:"/ref",
        element:<Suspense fallback={<div>正在加载中...</div>}><Ref/></Suspense>,
        meta:{
            title:"ref",
            isShow:true
        }
    },
  1. 封装 load 函数
// 封装 
let load = (Comp)=>{
    return (
        <Suspense fallback={<div>正在加载中...</div>}>
            <Comp/>
        </Suspense>
    )
}

react 中的路由模式

  1. BrowserRouter
  2. HashRouter 区别:
  3. 形式上 BrowserRouter 比较精简 HashRouter 路由地址栏上有锚点 hash #
  4. 兼容上 BrowserRouter 兼容 IE9 以上的浏览器 HashRouter 兼容 IE8 以上的浏览器
  5. 项目部署上 BrowserRouter 需要后台人员配置服务器 HashRouter 简单,直接项目打包,放在服务器就可以

redux

集中式状态管理工具 存储一些公共数据 token

  1. 安装 npm i redux --force
  2. 导入 import { createStore } from "redux"
// 1. 安装   npm i redux --force
// 2. 导入  createStore 创建数据仓库容器对象
import { createStore } from "redux"
// 3. 创建store 数据仓库
//    [1] 存什么数据
//    [2] 如何更新数据   action
//    action  描述一个行为/动作  值是一个对象  {type:"类型", payload:"更新时存储的数据"}
//   做作业 {type:"做",payload:"作业"}
//   玩游戏 {type:"玩",payload:"游戏"}
//   打酱油 {type:"打",payload:"酱油"}

let store = createStore((count=10,action)=>{
    // 加   {type:"incre",payload:1}
    // 减   {type:"decre",payload:2}
    // swich
    switch(action.type){
        case "incre":
           return count += action.payload;  // 返回的内容就是要更新默认数据的值
        case "decre":
            return count -= action.payload;
        // 第一次执行时会返回当前仓库中的默认值
        default:
            return count;
    }

});


// 4.     getState 获取数据
console.log(store.getState());


store 数据仓库 方法

  1. getState() 获取 store 中的数据
  2. dispatch() 分发行为 (1) 参数是 action 对象,则同步更新 {type:"",payload:""} (2) 参数 是 函数, 则异步更新
  3. subscribe() 订阅 当 store 仓库中的数据发生变化时候,会自动订阅到。

redux-thunk

作用: 中间件。支持异步更新store 数据

  1. 安装 npm i redux-thunk --force

  2. 在 store 中导入 import thunk from "redux-thunk"

  3. import { createStore,applyMiddleware } from "redux"
    applyMiddleware 作用 应用中间件

  4. 在 store 第二个参数 应用中间件


let store = createStore((count=0,action)=>{
    // 加   {type:"incre",payload:1}
    // 减   {type:"decre",payload:2}
    // swich
    switch(action.type){
        case "incre":
           return count += action.payload;  // 返回的内容就是要更新默认数据的值
        case "decre":
            return count -= action.payload;
        // 第一次执行时会返回当前仓库中的默认值
        default:
            return count;
    }

},applyMiddleware(thunk));

组件展示 store数据过程

  1. store,getState() ---> 找到 store , 找reducer ,找 state ,返回给 组件

  2. 更新数据 store.dispatch() ----> 找到 store , 找reducer , 找 action ,更新 state数据 , 返回给组件

合并reducer 函数

import { createStore,applyMiddleware,combineReducers } from "redux"

combineReducers 合并reduce函数,返回reducer对象

    let reducers = combineReducers({
        count:countReducer,
        zan:zanReducer
    })


// 3. 创建store 数据仓库
let store = createStore(reducers,applyMiddleware(thunk));


//   在组件中

     // 解构 store 数据
    //  store.getState();  获得的是一个store对象
    let {count,zan} = store.getState();

新版redux

  1. 安装 npm install @reduxjs/toolkit --force
  2. 导入
    // createSlice 创建 slice 切片对象 // configureStore 创建 store 对象 import {createSlice,configureStore} from "@reduxjs/toolkit"
  3. 创建 slice 对象 {}
    let countSlice = createSlice({
    //数据别名
    name:"count",  
    //设置数据初始值  
    initialState:{   //初始值 新版redux 推荐使用对象
        value:0
    },
    //创建  action 函数
    reducers:{
        //state    ===  initialState
        // action  行为、动作  {type: payload:}
        incre:(state,action)=>{
            //这里不能返回新数据,要直接更新数据
            state.value += action.payload;
        },
        decre:(state,{payload})=>{
            state.value -= payload;
        }
    }

})

// 4.  提取 action 方法
let {decre,incre} = countSlice.actions;

 
// 5. 创建 store 对象
let store = configureStore({
    reducer:countSlice.reducer
})

 // 6. 获取数据
console.log(store.getState());

// 7. 更新数据
console.log(store.dispatch(incre(10)));
console.log(store.getState());

console.log(store.dispatch(decre(5)));
console.log(store.getState());



react-redux

安装 npm i react-redux --force 导入: 在 入口文件 index.js 中导入 import {Provider} from "react-redux"

<Provider store={store}>
 当store 中的数据发生变化是,会立即监听到,重新渲染虚拟dom
</Provider >

// useSelector 会获取到store 中的所有数据 // useDispatch 会获取到store 中的dispatch 方法

typescript

安装 npm i -g typescript

  1. 创建 typescript --> 1. 初体验 ---> hello.ts
  2. 创建 ts 配置文件 tsc --init
  3. 转换为js tsc hello.ts

配置 webpack ts 运行环境

  1. 创建 .gitignore 忽略 node_modules
  2. 配置启动命令
//  package.json

 "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start":"npx webpack-dev-server",
    "build":"npx webpack"
  },

ts版本 react 脚手架

安装 create-react-app 项目名(只能小写) --template typescript 启动: npm start

UI框架

  1. bootstrap

antd

官网地址: ant.design/docs/spec/i…

安装核心: npm install antd --save
安装 图标库 : npm install --save @ant-design/icons

导入: 按需导入

代码仓库地址

gitee.com/helloguchen…