IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> React路由的补充及Redux的使用 -> 正文阅读

[JavaScript知识库]React路由的补充及Redux的使用

路由传递参数的方式

pramse传参

  • Route定义方式:<Route path=’/About/:id’ component={About} / >

  • Link组件:< Link to="/path/通过pramse传参">About
    在使用 params传递参数时,你会清楚的看到参数以路由的形式展现了出来,例如:

  • http://localhost:3000/home/message/用户1/文章32
    如果,你想传对象的话,可以用JSON.stringify(),想将其转为字符串,然后另外的页面接收后,用JSON.parse()转回去。这里简单提一下,不赘述。

传递 search 参数

这个就是依赖 get的请求方式。

  • http://localhost/home/message?id=1&title=abc

javascript 可以获取到 url? 后面的请求体。 所以我们可以吧上面的 map 中返回的标签修改以下

<li key={item.id}><Link to={`/home/message/detail?id=${item.id}&title=${item.title}`}>{item.title}</Link></li>

且这种方式不需要在路由中声明接收。
通过 props 中的 location 进行接收
query

  • Route定义方式:

  • Link组件 <Link to=’/Home?id=KaTeX parse error: Expected 'EOF', got '&' at position 3: {}&?title={}’’>Home
    state

  • Route定义方式:

  • Link组件:<Link to={{pathname: ‘/Home’,state:{传递的参数}}}>Download

  • 参数获取:this.props.location.state

- . withRouter 组件 让一般组件拥有路由组件的跳转功能

有的时候,我们想要在其他组件中也使用路由组件的功能,比如导航栏,应该属于公用组件,但是里面的导航链接的功能却是路由组件的功能,我们应该怎么解决呢?
react-router 中,提供了这么一种方法,可以让一般组件具有路由组件的功能,则就是 withRouter() 方法。
看看演示:

import {withRouter} from "react-router-dom";

class Header extends Component {
    // withRouter后该组件也有了路由组件的功能
    goBack = ()=>{
        this.props.history.goBack();
    }
    go = ()=>{
        this.props.history.go(2);
    }
    goForward = ()=>{
        this.props.history.goForward();
    }
    render() {
        return (
            <div>
                <h1>This is a React-router-dom Test!</h1>
                <button onClick={this.goBack}>goBack</button>
                &nbsp;
                <button onClick={this.goForward}>goForward</button>
                &nbsp;
                <button onClick={this.go}>go</button>
            </div>
        )
    }
}

// withRouter 用于给一般组件添加上路由组件特有的功能,返回一个新组件
export default withRouter(Header);

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7wReIXDU-1627644504523)(image/QQ%E6%B5%8F%E8%A7%88%E5%99%A8%E6%88%AA%E5%9B%BE20210729191109.png)]

假设我们的组件如同这张图一般,组件之间相互嵌套着。
这时候提出一个要求,在组件E中的数据,要给组件A组件F使用,要怎么处理呢?

  • 方法1:通过不断的 props进行传参,但是这非常的费时费力
  • 方法2:使用 Pubsub.js等进行消息发布/订阅功能
  • 方法3:使用 react-redux进行数据集中式管理

redux可以看作一个管家,负责帮忙存储公共的数据。

十、redux 的使用

在这里插入图片描述

假设我们的组件如同这张图一般,组件之间相互嵌套着。
这时候提出一个要求,在组件E中的数据,要给组件A组件F使用,要怎么处理呢?

  • 方法1:通过不断的 props进行传参,但是这非常的费时费力
  • 方法2:使用 Pubsub.js等进行消息发布/订阅功能
  • 方法3:使用 react-redux进行数据集中式管理

redux可以看作一个管家,负责帮忙存储公共的数据。

. 安装 redux

npm i redux -S

2. 核心概念

在这里插入图片描述
redux 有着三个核心概念

  1. action
    

    :

    • 动作的对象(操作内容)
    • 包含两个属性: a. type: 表示属性,值为字符串,唯一,必要属性(要干嘛) b. data: 数据属性,值为任意类型,可选属性(怎么干)
    • 例如:{ type: "ADD_STUDENT", data: { name: "tom", age: 18 } }
  2. reducer
    

    :

    • 用于初始化状态和加工状态(对数据进行初始化和操作数据的)
    • 加工时,根据旧的 stateaction,产生新的 state的纯函数
    • 有两个参数,一个为之前的状态(prevstate)与动作对象(action
  3. store
    

    :

    • stateactionreducer联系在一起的对象(大脑)

我们大致可以把 redux的想象成一家餐厅,而我们就是顾客( component),我们通过叫服务员( action)进行点餐等操作,服务员转达经理( store)后,经理吩咐后厨( reducer)进行做菜,然后把菜做好后由经理传递给顾客

3. 基本使用 redux

(1) 创建文件夹

src文件夹中创建 redux文件夹,用于存放 redux的相关内容

  • Compnoent ------ 存放组件相关的文件夹

  • redux

    ------ 存放

    redux
    

    相关内容的文件夹

    • actions ------ 存放 action相关内容的文件夹
    • reducers ------ 存放 reducer相关内容的文件夹
    • constant.js ------ 存放规范命名的文件
    • store.js ------ 编写 store的文件

由我来一个个带你们解析。先写一个最简单的 redux

/**
 * store.js
 * 该文件专门用于暴漏一个 store对象,整个应用只有一个 store对象
 */
// 引入 createStore,专门用于创建 redux中最为核心的 store
import {createStore} from "redux";
// 引入为 Count组件服务的 reducer
import countReducer from "./count_reducer";
const store = createStore(countReducer)
// 暴露 store对象
export default store;
复制代码
/**
 * / reducer / count.js
 * 1. 该文件是用于创建一个为 Count组件服务的 reducer,reducer的本质就是一个函数
 * 
 * 2. reducer函数会收到两个参数,分别为:之前的状态(preState),动作对象(action)
 * 
 * 3. 会自动调用一次 reducer(初始化)
 */
// 初始化的状态
const initState = 0;
export default function countReducer(preState = initState, action){
    if(preState === undefined) preState = 0; 
    // 从 action对象中获取 type,data
    const {type, data} = action;
    // 根据 type觉得如何加工数据
    switch (type) {
        case 'increment': // data
            return preState + data;
        case 'decrement': // 如果是减
            return preState - data;
        default:
            return preState;
    }
}
复制代码
// / Component / Count.js 
import React, { Component } from 'react'
// 引入store
import store from "../../redux/store";
export default class Count extends Component {
    // 加法
    increment = ()=>{
        const {value} = this.selectNumber;
        // 发送动作对象给 store
        store.dispatch({
            type: "increment",
            data: value*1
        })
    }
    render() {
        return (
            <div>
                <h1>当前求和为:{store.getState()}</h1>
                <select ref={c=>this.selectNumber = c}>
                    <option value="1">1</option>
                    <option value="2">2</option>
                    <option value="3">3</option>
                </select>
                <button onClick={this.increment}>+</button>
            </div>
        )
    }
}

这个必须加不然数据变了但页面不会变化

 componentWillMount(){

       console.log(store.subscribe)

        store.subscribe(()=>{

          this.setState({})

      })

   }
必须加上这段代码不然render函数不会调用页面不会变化

以上就是最精简的 redux,让我们分析一下流程:

  1. 编写 Count组件,创建 Count组件对应的 Reducer文件

  2. 编写

    Reducer
    

    的代码并抛出::

    • Reducer是个纯函数
    • 通常使用 Switch进行 action中的 type的判断
    • 函数返回值为修改后的值
  3. 创建

    store
    

    并编写代码:

    • 使用方法 createStore()方法来创建一个 store,参数是一个 reducer
    • 把编写好的 Count组件的 reducer导入
  4. 在组件中引入

    store
    

    并进行调用:

    • 在方法中通过使用 dspatch()方法向 store传递 action
    • dispatch的参数时一个对象(即 action动作对象)

(2) 使用流程

以上使创建的大致流程,而使用的大致流程是这样的:

  1. store 初始化时自动调用了一次 reducer进行了值的初始化
  2. 组件发出动 actionstorestore进行判断后分发给对应的 reducer
  3. reducer根据 action里的 type对数据进行相应的处理后返回新的值
  4. store接收返回的新的值,并将旧的值替换掉
  5. 通过方法 store.getState() 获取当前 store身上的值

(3) 使用异步redux

如果我们需要使用异步的 redux的话,还需要借助另一款插件: redux-thunk

npm i redux-thunk -S
复制代码

这是一个中间件,用于帮忙处理异步的 redux
异步的 action的值为一个函数 在函数中进行普通的 dispatch() 操作

export const createIncrementAsyncAction = (data, time=500)=>{
    // 返回一个 action
    return ()=>{
        setTimeout(()=>{
            store.dispatch(createIncrementAction(data));
        }, time);
    }
}
复制代码

同时我们要在 store处设置让他支持执行中间件,通过 reduxapplyMiddleware() 方法就可以加载中间件,他的参数就是中间件,然后 applyMiddleware() 将作为 createStore() 的第二个参数引入。

// store.js
// 引入 applyMiddleware,专门用于执行中间件
import {createStore, applyMiddleware} from "redux";
// 引入为 Count组件服务的 reducer
import countReducer from "./count_reducer";
// 引入 redux-thunk,用于支持异步 action
import thunk from "redux-thunk";
// 暴露 store对象
export default createStore(countReducer, applyMiddleware(thunk));
复制代码

(4) 监听状态变化

你写着写着有没有发现,虽然 redux里面的状态确实更新了,但是页面并没有变化啊?
还记得页面渲染使用的是哪个函数吗?render()函数。可是在 redux状态发生变化时,并不会帮助我们调用 render()函数,所以我们需要手动实现实时渲染页面。
在这里我们使用到了 reduxstore上的 subscribe() 方法,用于监听 redux上状态的变化,参数是一个函数,便于我们进行操作。
一般我们都写在根标签上(精简些,不用再每个使用 redux的组件中都写一遍)

import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import store from "./redux/store"
ReactDOM.render(
    <App />,
  document.getElementById('root')
);
// 精简写法
store.subscribe(()=>{
  ReactDOM.render(
      <App />,
    document.getElementById('root')
  );
})

4. 注意事项

  1. 一般使用到 redux的话,需要使用的组件肯定不止一个,所以创建 actionsreducers用来存储多个 actionreducer

  2. 同上,

    store
    

    肯定不止加载一个

    reducer
    

    ,所以我们使用

    redux
    

    combineReducers()
    

    方法来整合所有的

    reducer
    
    • combineReducers()方法的参数是一个对象,里面存放着所有的 reducer
import {createStore, applyMiddleware, combineReducers} from "redux";
import countReducer from "./reducers/count";
import personReducer from "./reducers/person";
import thunk from "redux-thunk";
// 汇总所有的 reducer
const allReducer = combineReducers({
    count: countReducer,
    persons: personReducer,
});
export default createStore(allReducer, applyMiddleware(thunk));
  1. 因为

    redux
    

    在设计上还有许多的问题,例如:

    • 单个组件需要做:与 store打交道,获取数据,监听数据变化,派发 action对象等,一个组件负责的事情太多了。
    • 需要另外监听 redux的状态变化来更新状态并渲染页面。
    • 所以有人对 redux进行了优化,推出了另一个库 react-redux(放心,没啥不同,就是多了点优化,后面会讲)
  2. 能不使用 redux,就不要使用 redux(不管是 redux 还是 react-redux)

  3. 能不使用 redux,就不要使用 redux(不管是 redux 还是 react-redux)

  4. 能不使用 redux,就不要使用 redux(不管是 redux 还是 react-redux)

总结

redux就是一个管理react数据的一个状态库,当我们很多地方需要使用到同一组数据的时候,就可以使用redux来管理我们的数据,避开了不必要的多层级,复杂化的传输数据,让我们的数据使用起来更加方便,高效,节省内存空间.

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-31 16:32:00  更:2021-07-31 16:35:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/6 19:11:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码