您的当前位置:首页>全部文章>文章详情

【React】前端框架 React 学习总结

CrazyPanda发表于:2023-12-05 20:31:32浏览:891次TAG: #php

目录

一、React在HTML里的运用

二、React框架的常用操作

项目打包

1、JSX基础语法规则

2、state数据的使用

3、生命周期

4、数据的双向绑定与Ref

5、PropTypes验证规则

6、React里的插槽

7、错误边界

8、直接操作refs元素

9、高阶组件的运用案例

10、性能优化

11、Hook生命周期钩子的使用

12、React里的计算属性

三、组件之间的传值

1、父子组件之间传值

2、子向父传值

3、context实现跨层级通信

context hook案例

四、网络请求框架使用

五、React路由的使用

声明式导航

编程式导航

编程式跳转

六、Anti Desgin的使用实现UI界面

七、Redux中央仓库的使用

1、新建src/redux/index.js用于存放redux的文件

2、在src/index.js里引入

3、可以通过logger查看redux日志

4、Redux的模块化管理

5、注意事项

6、总结Redux使用的完整步骤



一、React在HTML里的运用

React在HTML里的使用核心就是导入3个依赖:

<!--React核心库--><script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script><!--React-dom用于支持react操作DOM--><script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script><!--引入babel用于将jsx转为js--><script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>

案例代码如下:

<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><title>test</title></head><body><div id="root"></div></body><!--React核心库--><script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script><!--React-dom用于支持react操作DOM--><script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script><!--引入babel用于将jsx转为js--><script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script><!--这里一定要用这个type,让babel翻译script标签中的代码--><script type="text/babel">//1、创建虚拟Dom// 方式一  JSXconst VDOM = (<h1 id="title"><span>Hello,React</span></h1>)//方式二 js语法创建DOM// const VDOM=React.createElement("h1",{id:"title"},React.createElement("span",{},"Hello,React"))//2、将虚拟DOM转成真实DOM,并插入页面ReactDOM.render(VDOM, document.getElementById("root"))</script></html>

运行效果:

执行流程如下:

b5a77db0cdbd436188c23d52d8838748.png

二、React框架的常用操作

脚手架创建:

使用详情查看官网,这里只记录我的笔记:React 官方中文文档 – 用于构建用户界面的 JavaScript 库

npx create-react-app projectName

项目打包

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

 打包时为了路径对应需要到package.json中添加"homepage":"./"这一属性。

1、JSX基础语法规则

b5a77db0cdbd436188c23d52d8838748.png

案例代码:object对象不能执行渲染,arr可以通过map函数进行遍历输出。

import React from 'react';function App () {const num=16const bool=trueconst name="string"const arr=[1,2,3,4,"Jack",true]const obj={name:"Mary",age:12}return(<div style={{marginLeft:"20px"}}><div>num:{num}</div><div>bool:{bool}</div><div>name:{name}</div><div>arr:{arr}</div><div>arr遍历: {arr.map((item,index)=>(<p key={index}><span color={"red"}>{item}</span></p>))}</div>{/*对象不能直接打印*/}{/*<div>obj:{obj}</div>*/}<div>obj.name:{obj["name"]}</div></div>)}export default App;

效果:

b5a77db0cdbd436188c23d52d8838748.png

2、state数据的使用

参考文档:State & 生命周期 – React

b5a77db0cdbd436188c23d52d8838748.png

3、生命周期

发送网络请求一般在componentDidMount里执行,

销毁组件开销一般在componentWillUnmount里执行。

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

4、数据的双向绑定与Ref

方法一: 

class Test extends Component {
    
    constructor (props, context) {
        super(props, context)
        this.state={
            val: "233"
        }
    }
    
    changeVal=(e)=>{
        console.log(e)
        this.setState({
            val: e.target.value
        })
        console.log(e.target.value)
    }
    
    render () {
        return (
            <div>
                <input type="text" onChange={this.changeVal} value={this.state.val} />
            </div>
        )
    }
}

方法二:通过ref实现

class Test extends Component {
    
    constructor (props, context) {
        super(props, context)
        this.state={
            val: "233"
        }
        //1、在构造函数里创建ref的语法
        this.myRef=React.createRef()
    }
    
    search=()=>{
        //3、获取DOM元素
        console.log(this.myRef.current.value)
    }
    
    render () {
        return (
            <div>
                {/*2、绑定到元素上去*/}
                <input type="text" ref={this.myRef} onChange={this.search}/>
            </div>
        )
    }
}

refs的操作参考:

Refs and the DOM – React

5、PropTypes验证规则

参考:

使用 PropTypes 进行类型检查 – React

6、React里的插槽

参考:

组合 vs 继承 – React

7、错误边界

避免一错全不渲染的情况

参考:错误边界 – React

8、直接操作refs元素

函数组件里使用:

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

参考:Refs 转发 – React

9、高阶组件的运用案例

参考:高阶组件 – React

实现组件加载时间的复用

import React from "react"
 
export default function showTime (Comp) {
    return class extends React.Component {
        constructor (props, context) {
            super(props, context)
            this.state = {
                startTime: new Date().getTime(),
                loadingTime: 0
            }
        }
        
        componentDidMount () {
            let endTime = new Date().getTime()
            this.setState({
                loadingTime: endTime - this.state.startTime
            })
        }
        
        render () {
            return (
                <Comp loadingTime={this.state.loadingTime}/>
            )
        }
    }
}

这样便实现了高阶组件的复用,需要使用这个功能时,只需要调用该函数对象进行功能追加即可。

10、性能优化

参考:性能优化 – React

1、新版本以后Component用PureComponent,

PureComponent自带state和props的检查,但其中有变化时才重写渲染,否则不重新渲染,提升性能。

函数组件中的优化:相当于pureComonent

React.memo()生命周期钩子,相当于pureCompnent会在props和state变化时才发生更新。

案例代码:

import React from "react"
 
const componentTwo = React.memo((props) => {
    return (
        <div>
        
        </div>
    )
})
 
export default componentTwo

2、组件用完后资源记得释放

11、Hook生命周期钩子的使用

参考:Hook API 索引 – React

使用函数组件的效率一般会比类组件效率高一些,但在函数组件(无状态组件)中又没有state等属性,所以这里诞生了Hook为函数组件添加state和生命周期等元素。

Hook 简介 – React

案例一: useState  修改状态

import React,{useState} from "react"
 
function FunComponentOne () {
    //定义一个变量,初始值为0,可通过setCount方法修改值
    //第一个位置变量名,第二个位置方法名:修改变量的方法
    const [count,setCount]=useState(0)
    
    return (
        <div>
            <h2>{count}</h2>
            <button onClick={()=>setCount(count+1)}>+</button>
        </div>
    )
}
 
export default FunComponentOne

案例二:useEffect  生命周期钩子

b5a77db0cdbd436188c23d52d8838748.png

import React,{useState,useEffect} from "react"function FunComponentOne () {//定义一个变量,初始值为0,可通过setCount方法修改值//第一个位置变量名,第二个位置方法名const [count,setCount]=useState(0)//第二个参数为空,相当于生命周期钩子:componentDidMount+componentDidUpdate//加载完成和数据修改都会走该函数useEffect(() => {console.log("=======================")})//第二个参数为空数组[],相当于componentDidMount,可以用于网络请求useEffect(() => {console.log("++++++++++++++++++++++++++++")}, [])//第二个参数可以传入有值的数组,当数组里的变量修改,会调用该函数useEffect(() => {console.log("!!!!!!!!!!!!!!!!!!!!!!!!!")}, [count])//当第二个参数为空数组[],且有返回函数时相当于componentWillUnMount//一般用于销毁主键useEffect(() => {return function clearUp(){console.log("clearUp")}},[])return (<div><h2>{count}</h2><button onClick={()=>setCount(count+1)}>+</button></div>)}export default FunComponentOne

案例3: Hook reducer类似于升级版的useState

参考:Hook API 索引 – React

案例4:自定义Hook 降低耦合度

参考:自定义 Hook – React

可以将频繁调用的hook定义到自己的hook里,注意要用use开头

b5a77db0cdbd436188c23d52d8838748.png

12、React里的计算属性

相当于Vue里的Computed

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png


三、组件之间的传值

b5a77db0cdbd436188c23d52d8838748.png

1、父子组件之间传值

通过组件传参的方式:

<ChildOne num={12}/>
<ChildTwo num={24}/>

子组件接收参数:

class ChildTwo extends Component {
    render () {
        return (
            <div>
                <h2>我是子组件ChildTwo: {this.props.name}</h2>
            </div>
        )
    }
}
 
function ChildOne (prop) {
     return(
         <div>
             <h2>ChildOne子组件:{prop.num}</h2>
         </div>
     )
}

2、子向父传值

通过父组件传递方法对象给子组件,子组件再调用该方法并传入对应参数和处理给父组件。

父组件:

function ParentOne () {
    function getSonData (data) {
        console.log(data)
    }
    
    return (
        <div>
            <ChildThree getSonData={getSonData} />
        </div>
    )
}

子组件:

 function ChildThree (prop) {
     function sendData(){
         prop.getSonData("我是子组件的数据")
     }
     return(
         <div>
             <button onClick={sendData}>点击向父组件传值</button>
         </div>
     )
 }

这里父组件将getSonData方法对象先传递给子组件,子组件拿到方法对象后可以通过prop进行调用并传入子组件的参数到方法里,此时会调用父组件里的方法以拿到子组件的数据。

3、context实现跨层级通信

参考:Context – React

 (1)首先,创建一个MyContext.js用来管理context环境变量

import React from "react"
//创建中间仓库
const MyContext=React.createContext(undefined)
 
export default MyContext

(2)案例

第一层父组件,提供数据

class LayerOne extends Component {
    
    constructor (props, context) {
        super(props, context)
        this.state={
            name: "cute Tom"
        }
    }
    
    render () {
        return (
            <div>
                <h1>我是one</h1>
                <MyContext.Provider value={this.state}>
                    <LayerTwo/>
                </MyContext.Provider>
            </div>
        )
    }
}

第二层:包含第三层

class LayerTwo extends Component {
    render () {
        return (
            <div>
                <h2>我是two</h2>
                <LayerThree/>
            </div>
        )
    }
}

第三层可以直接消费数据,注意这里需要声明一下是哪个MyContext

class LayerThree extends Component {
    render () {
        return (
            <div>
                <h3>我是three</h3>
                <MyContext.Consumer>
                    {value => <div><h2>{value.name}</h2></div>}
                </MyContext.Consumer>
            </div>
        )
    }
}
 
LayerThree.contextType=MyContext

效果:

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

context hook案例

函数组件中的使用:Context Hook

b5a77db0cdbd436188c23d52d8838748.png

链接:useContext使用 - 简书 

四、网络请求框架使用

见我博客:

前端框架 网络请求 Fetch Axios_Dragon Wu的博客-CSDN博客

五、React路由的使用

官方文档:React Router: Declarative Routing for React.js

参考:

React Router 6 (React路由) 最详细教程-阿里云开发者社区

6.v新特性:

react-router 6 新特性总结 - 知乎

首先安装依赖:

yarn add react-router-dom@6

声明式导航

(推荐使用编程式导航效率更高)

案例代码:一般使用BrowseRouter有history记录

import React, { Component } from "react"
import { BrowserRouter, Routes, Route, Navigate, NavLink, useParams,Link,Outlet } from "react-router-dom"
 
class Home extends Component {
    render () {
        return (
            <div>
                <h1>Home</h1>
            </div>
        )
    }
}
 
class About extends Component {
    render () {
        return (
            <div>
                <h1>About</h1>
            </div>
        )
    }
}
 
function Detail () {
    
    console.log(useParams())
    return (
        <div>
            <h2>详情</h2>
            <p>id: {useParams().id}</p>
        </div>
    )
}
 
function Main(){
    return (
        <div>
            <h1>文档</h1>
            <Link to={"/doc/one"}>文档1</Link>
            <Link to={"/doc/two"}>文档2</Link>
            <Link to={"/doc/three"}>文档3</Link>
            {/*嵌套路由时注意书写这个标签*/}
            <Outlet/>  {/* 指定路由组件呈现的位置 */}
        </div>
    )
}
 
function App () {
    
    return (
        <div>
            <BrowserRouter>
                <div>
                    <NavLink to={"/home"}>首页</NavLink>|
                    <NavLink to={"/about"}>关于</NavLink>|
                    <NavLink to={"/detail/123"}>详情</NavLink>|
                    <NavLink to={"/doc"}>文档</NavLink>
                </div>
                <Routes>
                    <Route path={"/home"} element={<Home />} />
                    <Route path={"/about"} element={<About />} />
                    {/*嵌套路由*/}
                    <Route path={"doc"} element={<Main/>}>
                        <Route path={"one"} element={<h3>one</h3>} />
                        <Route path={"two"} element={<h3>two</h3>} />
                        <Route path={"three"} element={<h3>three</h3>} />
                    </Route>
                    {/*动态路由*/}
                    <Route path={"/detail/:id"} element={<Detail />} />
                    {/*路由重定向,也可用于404处理*/}
                    <Route path="/*" element={<Navigate to="/home" replace />} />
                    {/*404处理*/}
                    <Route path="*" element={<NotFound />} />
                </Routes>
            </BrowserRouter>
        </div>
    )
}
 
export default App
 
// 用来作为 404 页面的组件
const NotFound = () => {
    return <div>你来到了没有知识的荒原</div>
}

b5a77db0cdbd436188c23d52d8838748.png

编程式导航

(1)新建src/router/index.js文件

import { Navigate } from "react-router-dom"
import Home from "../page/home/Home"
import HomeLeft from "../page/home/HomeLeft"
import HomeRight from "../page/home/HomeRight"
import About from "../page/About"
import Detail from "../page/Detail"
const routes=[
    {
        path: "/",
        element: <Navigate to="/home" />
    },
    {
        path: "home",
        element: <Home />,
        children: [
            {
                index: true,
                element: <HomeLeft />
            },
            {
                path: "right",
                element: <HomeRight />
            }]
    },
    {
        path: "/about",
        element: <About />
    },
    {
        path: "/detail",
        element: <Detail />
    },
    { path: "*", element: <p>404页面不存在</p> }
]
export default routes

(2)为src/index.js添加BrowserRouter容器

注意: BrowserRouter必须在App标签的外层

b5a77db0cdbd436188c23d52d8838748.png

 (3)App.js如下:

import React from 'react'
import routes from "./router/index.js"
import {useRoutes,NavLink } from "react-router-dom"
 
 function App () {
     // useRoutes可以用路由表生成<Routes>...</Routes>结构
     // 根据路由表生成对应的路由规则
     const element = useRoutes(routes)
     
     return(
         <div id="App">
             <div>
                 <NavLink to={"/home"} >首页</NavLink>|
                 <NavLink to={"/about"}>关于</NavLink>|
                 <NavLink to={"/detail"}>详情</NavLink>
             </div>
             <div>
                 {element}
             </div>
         </div>
     )
 }
 
 export default App
(4)若有嵌套路由要使用<Outlet/>标签标明子组件插入的位置
class Home extends Component {
    render () {
        return (
            <div>
                <h1>Home</h1>
                <Link to={"/home/right"}>homeRight</Link>
                <Link to={"/home"}>homeLeft</Link>
                {/*嵌套路由时注意书写这个标签*/}
                <Outlet/>  {/* 指定路由组件呈现的位置 */}
            </div>
        )
    }
}

编程式跳转

默认是push 模式

export default function HomeNews() {
  const navigate = useNavigate();
  const jump = ()=>{
    navigate('/home')
  }
  return (
      <News>
        <button onClick={jump}>点击跳转</button>
      </News>
  )
}

使用{replace:true} 就会变为replace模式

navigate('/home', { replace: true });

也可以使用 navigate(-1) 传入一个数字来进行跳转

navigate(1)//传入数字

六、Anti Desgin的使用实现UI界面

官方文档:Ant Design - A UI Design Language

1、添加到项目:

yarn add antd

2、样式引入

全局映入样式:在src/index.js里引入样式,不推荐,会导入很多无用的样式

import 'antd/dist/antd.css';  
// or 'antd/dist/antd.less'

按需映入,推荐

下面两种方式都可以只加载用到的组件。

  • 使用 babel-plugin-import(推荐)。

  • b5a77db0cdbd436188c23d52d8838748.png

  • yarn add babel-plugin-import

    b5a77db0cdbd436188c23d52d8838748.png

    1. // .babelrc or babel-loader option
    2. {
    3. "plugins": [
    4. ["import", { "libraryName": "antd", "style": "css" }] // `style: true` 会加载 less 文件
    5. ]
    6. }
  • 然后只需从 antd 引入模块即可,无需单独引入样式。等同于下面手动引入的方式。


    1. // babel-plugin-import 会帮助你加载 JS 和 CSS
    2. import { DatePicker } from 'antd';
  • 手动引入


    1. import DatePicker from 'antd/lib/date-picker';  // 加载 JS
    2. import 'antd/lib/date-picker/style/css';        // 加载 CSS
    3. // import 'antd/lib/date-picker/style';         // 加载 LESS

3、组件里直接调用即可

b5a77db0cdbd436188c23d52d8838748.png

七、Redux中央仓库的使用

当我们的项目稍微复杂一些时,原生的state可能无法高效的管理和操作数据缓存,通过Redux可以将数据统一管理,并且减低代码耦合。

参考:入门 Redux | Redux 中文官网

b5a77db0cdbd436188c23d52d8838748.png

b5a77db0cdbd436188c23d52d8838748.png

 其工作原理与hook reducer类似

yarn add @reduxjs/toolkit

安装参考:安装 | Redux 中文官网

1、新建src/redux/index.js用于存放redux的文件

//1、引入redux
import { configureStore } from "@reduxjs/toolkit"
 
//2、创建仓库
const store = configureStore({reducer})
 
//3、reducer为store服务的执行者, action={type:"",data:5}
function reducer (preState = 10, action) {
    switch (action.type) {
        case "add":
            return preState + action.data
        case "sub":
            return preState - action.data
        default:
            return preState
    }
}
 
//4、使用store
console.log(store)
//获取仓库的数据
console.log(store.getState())
//触发action
store.dispatch({
    type: "add",
    data: 5
})
console.log(store.getState())

2、在src/index.js里引入

b5a77db0cdbd436188c23d52d8838748.png

运行结果:可以看到数据已经被操作了

b5a77db0cdbd436188c23d52d8838748.png

3、可以通过logger查看redux日志

yarn add redux-logger

添加logger后:

//1、引入redux
import { configureStore } from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"
 
//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    reducer,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})
 
//3、reducer为store服务的执行者, action={type:"",data:5}
function reducer (preState = 10, action) {
    switch (action.type) {
        case "add":
            return preState + action.data
        case "sub":
            return preState - action.data
        default:
            return preState
    }
}
 
//4、使用store
console.log(store)
//获取仓库的数据
console.log(store.getState())
//触发action
store.dispatch({
    type: "add",
    data: 5
})
console.log(store.getState())

可以看到日志的打印:

b5a77db0cdbd436188c23d52d8838748.png

合并多个reducer 

//1、引入redux
import { configureStore} from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"
 
//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    //合并多个reducer
    reducer:{
        reducer,
        reducer2
    },
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})
 
//3、reducer为store服务的执行者, action={type:"",data:5}
function reducer (preState = 10, action) {
    switch (action.type) {
        case "add":
            return preState + action.data
        case "sub":
            return preState - action.data
        default:
            return preState
    }
}
 
function reducer2 (preState = { user: "", num: 5 }, action) {
    const { type, data } = action
    let newState = { ...preState }
    switch (type) {
        case "addUser":
            newState.user = data.user
            return newState
        case "delUser":
            newState.user = ""
            return newState
        default:
            return newState
    }
}
 
//4、使用store
console.log(store)
//获取仓库的数据
console.log(store.getState())
// //触发action
store.dispatch({
    type: "add",
    data: 5
})
console.log(store.getState())
 
store.dispatch({
    type: "addUser",
    data: {
        user: "大猫"
    }
})
 
store.dispatch({
    type: "delUser"
})

运行结果:

b5a77db0cdbd436188c23d52d8838748.png

4、Redux的模块化管理

项目书写时我们需要加上命名空间以避免重复:

b5a77db0cdbd436188c23d52d8838748.png

另外,我们还需要将常量单独提取到一个文件里管理:

b5a77db0cdbd436188c23d52d8838748.png

分类管理reducers:

b5a77db0cdbd436188c23d52d8838748.png

 reducer/index.js: 引入所有reducers方便调用

import { count } from "./countReducer"
import {user} from "./userReducer"
 
export const reducers={
    count,
    user
}

redux/index.js引入reducer的索引文件即可:

//1、引入redux
import { configureStore} from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"
 
//引入reducers
import { reducers } from "./reducers"
 
//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    //合并多个reducer
    reducer: reducers,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})

5、注意事项

返回值注意:

书写时最好按照这种格式的逻辑:

b5a77db0cdbd436188c23d52d8838748.pngb5a77db0cdbd436188c23d52d8838748.png

redux默认不支持异步操作,一般实现思路是等异步任务做完后同步回调时进行redux操作:

b5a77db0cdbd436188c23d52d8838748.png

6、总结Redux使用的完整步骤

安装依赖:

yarn add @reduxjs/toolkityarn add react-redux

日志依赖:

yarn add redux-logger

(1)创建store仓库,reducers分开管理

reducers:  数据开发中type字符串应放入一个常量管理

b5a77db0cdbd436188c23d52d8838748.png

export function count(preState={num:0},action){
    const {type,data}=action
    let newState={...preState}
    switch (type) {
        case "num/add":
            newState.num+=data.num
            return newState
        case "num/sub":
            newState.num-=data.num
            return newState
        default:
            return newState
    }
}
export function user(preState={user:{name:"",age:1}},action){
    const {type,data}=action
    let newState={...preState}
    switch (type) {
        case "user/update":
            newState.user=data.user
            return newState
        case "user/delete":
            newState.user={name:"",age:1}
            return newState
        default:
            return newState
    }
}

索引所有reducers:

import { count } from "./countReducer"
import { user } from "./userReducer"
 
export const reducers = {
    count,
    user
}

创建store仓库并开启日志:

//1、引入redux
import { configureStore } from "@reduxjs/toolkit"
//引入日志
import { logger } from "redux-logger/src"
 
//导入reducers
import { reducers } from "./reducers"
 
//2、创建仓库
// const store = configureStore({reducer})
const store = configureStore({
    //合并多个reducer
    reducer: reducers,
    middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(logger)
})
 
 
export default store

(2)导入到src/index.js文件,全局配置

b5a77db0cdbd436188c23d52d8838748.png

(3)组件中的使用

import React from "react"
import { connect } from "react-redux"
 
function ReduxTestComp (props) {
    return (
        <div>
            <h1>count: {props.count.num}</h1>
            <h1>user:{props.user.user.age},{props.user.user.name}</h1>
            <button onClick={()=>props.updateUser({user:{ name: "Jack", age: 12 }})}>修改用户</button>
            <button onClick={()=> props.deleteUser()}>删除用户</button>
            <button onClick={()=>props.addNum()}>+</button>
        </div>
    )
}
 
export default connect((state) => {//读取仓库中所有state
    console.log(state)
    return {
        count: state.count,
        user: state.user
    }
}, (dispatch) => {//action操作
    console.log(dispatch)
    return {
        updateUser: (data) => {
            return dispatch({ type: "user/update", data: data })
        },
        deleteUser: ()=>{
            return dispatch({type:"user/delete"})
        },
        addNum:()=>{
            return dispatch({type:"num/add",data:{num:12}})
        }
    }
})(ReduxTestComp)
import React from "react"
import ReduxTestComp from "./component/reduxTest/ReduxTestComp"
 
function App () {
    
    return (
        <div id="App">
            <ReduxTestComp />
        </div>
    )
}
 
export default App

至此,实现redux的全程应用。

猜你喜欢

【AntDesignPro】Ant Design Pro学习记录—ModalForm的使用(三)
一、 Form.useForm()的使用之前使用表单的时候,一直在为表单赋值纠结,找了一些资料,也感觉很复杂,使用多了之后,感觉表单赋值也挺简单的。1、 创建一个formconst&nbsp;[theForm]&nbsp;=&nbsp;Form.useForm();2、 绑定表单组件无论是ProForm、ModalForm、还是DrawerForm,都可以绑定我们的theForm,使用属性form={theForm}绑定,代码如下&lt;ProForm &nbsp;&nbsp;&nbsp;&amp;nb
发表于:2024-02-20 浏览:473 TAG:
【React】使用React实现一个内容滑动组件
最近在做项目时遇到一个需求,需要让一个列表能够通过点击按钮进行滚动,每次都是一屏的距离,不足则结束。并且,这个列表项是在react-grid-layout中的某一个模块内。所以包裹这个列表的容器会随时发生变化。在完成这个组件后,通过这篇文章总结一下。UI/原型分析那么从上面的功能描述以及项目中的UI,我们可以分析得到这样一个假想图:我们需要实现一个容器来作为我们的可视区域,并且这个容器是可以伸缩的。列表内容如果超出容器的可视区域,那么就会被隐藏。需要左右都有按钮,来支持用户左右滑动内容来查看,每
发表于:2024-04-10 浏览:330 TAG:
【React】React前端图片裁剪组件
前端图片裁剪组件前端图片裁剪已经是很常见的需求了,在 react 的项目中推荐使用 react-image-crop 库,能勾勒出裁剪区域、宽高比例限制等等,但是还是有很多东西需要我们来做的,比如以下问题:react-image-cropreact-image-crop 的基本使用import&nbsp;ReactCrop&nbsp;from&nbsp;&quot;react-image-crop&quot;; import&nbsp;&quot;react-image-crop/dist/Re
发表于:2024-03-29 浏览:309 TAG:
【AntDesignPro】Ant Design Pro学习记录—ProTable的使用(二)
目录一、列表检索初始值设置二、字段缩略显示一、列表检索初始值设置使用initialValue属性,配置列表检索的初始值const&nbsp;columns:&nbsp;ProColumns&lt;API.RoomItem&gt;[]&nbsp;=&nbsp;[ &nbsp;&nbsp;&nbsp;&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title:&nbsp;&#39;名称&#39;,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp;nb
发表于:2023-11-28 浏览:709 TAG:
【AntDesignPro】Ant Design Pro学习记录—DrawerForm的使用
在AntDesignPro中,ModalForm和DrawerForm是我最常用的两个表单组件,配置上,他们有很多相同的地方,也有差异的地方,相比较而言,DrawerForm我使用的更多。ModalForm&lt;ModalForm &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;title={标题} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;width={600} &nbsp;&nbsp;&amp;n
发表于:2024-05-17 浏览:468 TAG:
【AntDesignPro】Ant Design Pro学习记录—ProTable的使用(一)
目录一、关于ProTable二、使用步骤1.新建页面2.修改接口3.接口调用4.数据显示和检索1)不同类型内容显示2)列表检索3)列表内容样式设置5.其它1)render的简单使用2)图片点击预览3)翻页总结前言因为项目需要,确定了Ant Design Pro框架来开发后台管理端,刚接触这套框架,而且配套的资料真的很少,只能基于官方demo和网上不完整的学习经验一次次尝试,终于有个像样的结果,记录一下研究学习的成果,也给需要的同学一些帮助。本次学习研究基于Ant Design Pro V5版本,
发表于:2023-11-28 浏览:836 TAG: #前端 #antd #AntDesignPro
【React】前端框架 React 学习总结
目录一、React在HTML里的运用二、React框架的常用操作项目打包1、JSX基础语法规则2、state数据的使用3、生命周期4、数据的双向绑定与Ref5、PropTypes验证规则6、React里的插槽7、错误边界8、直接操作refs元素9、高阶组件的运用案例10、性能优化11、Hook生命周期钩子的使用12、React里的计算属性三、组件之间的传值1、父子组件之间传值2、子向父传值3、context实现跨层级通信context hook案例四、网络请求框架使用五、React路由的使用声明
发表于:2023-12-05 浏览:892 TAG: #php
【AntDesignPro】L7Plot地理可视化组件的使用
L7Plot介绍L7Plot 基于&nbsp;L7&nbsp;实现的开箱即用地理空间数据可视化图表库L7Plot 专注于地理可视化图表。以声明配置式的方式,降低用户使用成本;以常见地理图表分类的方式,降低用户选择成本;内部集成全国行政区域数据,降低用户使用地理数据心智;支持多图层及多图表层叠,方便用户定制复杂的业务场景;L7Plot 专注于地理数据可视化展示,不会涉及数据编辑能力。前言项目需要,使用antdesignpro做前端,并绘制可视化大屏,回执地图组件,于是使用了L7Plot。功能目的绘
发表于:2023-12-14 浏览:670 TAG:
【React】如何在 React 类中声明常量?
使用 react 开发应用程序时,有必要声明常量来存储在组件或应用程序的整个生命周期中保持不变的值。常量可以帮助提高代码可读性,提供管理共享值的中心位置,并增强可维护性。在本文中,我们将探讨如何在 react 类组件中声明常量。导入 React首先,我们假设您已经设置了 React 环境并且有一个可供使用的类组件。在声明常量之前,请确保您已导入必要的库。这包括导入 React,它是在 React 中构建用户界面的核心库。import&nbsp;React&nbsp;from&nbsp;&#39;
发表于:2024-04-16 浏览:302 TAG:
【React】16 个实用的 React 库
Web开发中,经常会需要使用第三方库来提高开发效率。今天给大家分享16个非常实用的React第三方库,使用好这些库你可以更轻松、更快速的开发项目,让我们一起看看吧!1.react-hook-formReact-hook-form 是一个用于构建 Web 应用程序的表单库。它支持多种表单类型,包括输入框、下拉框、单选框、多选框等。它还提供了一些自定义选项,可以自定义表单的外观和行为。官方地址:https://react-hook-form.com/2.rechartsRecharts 是一个用于构
发表于:2024-04-01 浏览:303 TAG: