当前位置: 首页 > wzjs >正文

建站之星成品网站源码360免费建站

建站之星成品网站源码,360免费建站,企业为什么要做网络营销推广,网站互动功能状态管理库,集中式存储状态,管理状态 ✅ redux //简单实现 redux源码 export function createStore(reducer) {// reducer由用户编写, 必须是一个函数,dispatch的时候,reducer要执行if (typeof reducer ! function) t…

状态管理库,集中式存储状态,管理状态

✅ redux

在这里插入图片描述

//简单实现 redux源码
export function createStore(reducer) {// reducer由用户编写, 必须是一个函数,dispatch的时候,reducer要执行if (typeof reducer !== 'function') throw new Error('reducer必须是一个函数')let state // 公共状态let listeners = [] //事件池// 1.获取公共状态  store.getState()const getState = () => {return state}// 2.组件更新方法 进入事件池const subscribe = listener => {if (typeof listener !== 'function') throw new Error('listener 必须是一个函数')// 去重,防止重复添加if (!listeners.includes(listener)) {// 让组件更新的方法进入事件池listeners.push(listener)}// 返回一个函数,用于从事件池中删除对应的方法 (取消订阅)return function unsubscribe() {// 找到事件池中的对应方法,并删除listeners = listeners.filter(l => l !== listener)}}// 3.派发任务通知 Reducer 执行const dispatch = action => {// 必须是对象if (typeof action !== 'object') throw new Error('action 必须是一个对象')// 必须有 type 属性if (typeof action.type === 'undefined') throw new Error('action 必须有 type 属性')// 执行 reducer,参数为当前 state 和 action动作,返回新的 stateconst nextState = reducer(state, action)// 更新 公共状态state = nextState// 通知事件池中的方法,更新组件for (let i = 0; i < listeners.length; i++) {const listener = listeners[i]listener()}}// 4.redux初始化statedispatch({ type: '@@redux/INIT' })// 5. 返回 store 对象 { getState, dispatch, subscribe }return {getState,dispatch,subscribe}
}

1. 重要概念

状态是只读的,
后续修改状态的方式是通过Reducer(纯函数)接收旧状态和 Action,返回新状态。
Reducer无副作用,同样的输入必然得到同样的输出。


为什么reducer 不能直接更改状态?

  1. redux内部通过比较新旧状态的引用 来判断状态是否变化,接修改原状态,新旧状态的引用相同,Redux 会错误地认为状态未更新,致组件不重新渲染。
  2. 可预测性:
    直接修改状态 会导致变更分散在代码各处,难以追踪变化的来源。
    通过强制所有变更都集中在 reducer 中,使状态变化更透明、可维护。

2. 数据流

  1. 组件通过 dispatch(action) 发送 Action。
  2. Redux 调用对应的 Reducer,生成新状态。
  3. Store 更新状态,通知所有订阅了 Store 的组件。
  4. 组件通过 getState() 获取新状态并重新渲染。

⚠️⚠️ Redux 的监听机制 问题

  1. Redux 的 Store 维护一个订阅者列表 listeners= [],每次调用 dispatch(action) 时:
  2. Reducer 生成新状态(newState)。
  3. Store 用 newState 替换当前状态。
  4. ​遍历执行所有订阅者​(如 store.subscribe(listener) 注册的回调)。
    这意味着,​无论状态树中的哪一部分被修改,所有订阅者都会收到通知
    更改了 a状态,未使用a状态,使用了b状态的组件也会重新渲染。

解决: 使用 React-Redux 的 useSelector 或 connect

React-Redux :
其核心设计是 ​​「结构性共享」​​(仅更新变化部分的引用,未变化部分保留原引用)
通过 浅比较选择的状态引用,仅更新 引用变化的订阅组件,避免无关组件渲染。


问:Store 更新状态,如何通知组件更新?
通过Store内部的Subscription(listener)方法,listener 通常是 ​触发组件重新渲染的函数,或是 ​与组件更新相关的副作用逻辑。见下:

  1. 类组件:listener 通常是调用 this.forceUpdate() 的函数,强制组件重新渲染。
class Counter extends React.Component {componentDidMount() {// 定义 listener:强制组件重新渲染this.unsubscribe = store.subscribe(() => {this.forceUpdate();});}componentWillUnmount() {this.unsubscribe(); // 取消订阅}render() {const count = store.getState().count;return <div>{count}</div>;}
}
  1. 函数组件:listener 是 useState 的 副作用函数
import React, { useState, useEffect } from 'react';
import store from './store';function Counter() {// 定义forceUpdate 单纯是为了触发组件渲染更新,属性无意义 const [_, forceUpdate] = useState(0);  useEffect(() => {// 定义 listener:强制组件重新渲染const unsubscribe = store.subscribe(() => {forceUpdate(prev => prev + 1);});return unsubscribe; // useEffect 清理函数中取消订阅}, []);const count = store.getState().count;return <div>{count}</div>;
}
  1. 使用 react-redux 的 connect: connect 高阶组件内部会处理订阅逻辑,listener 是​比较新旧 props 并决定是否更新组件的函数。
    connect 是 高阶函数,内部会将公共状态以props的方式传递给组件。
import { connect } from 'react-redux';class Counter extends React.Component {render() {return <div>{this.props.count}</div>;}
}// 映射状态到 props
const mapStateToProps = (state) => ({count: state.count,
});// connect 内部逻辑(简化):
// 1.  Store的监听器会比较新旧 mapStateToProps 的结果。
// 2. 若结果变化,则触发组件更新。
export default connect(mapStateToProps)(Counter);
  1. react-redux 的 useSelector钩子
    useSelector 的 listener 是 ​检查选择器返回值是否变化,并触发重新渲染 的函数。
import { useSelector } from 'react-redux';function Counter() {// 内部实现(简化):// 1. 订阅 Store,监听器会比较新旧 selector(state) 的结果。// 2. 若结果变化,则触发组件重新渲染。const count = useSelector((state) => state.count);return <div>{count}</div>;
}

❤️❤️❤️ React-Redux

对redux 进行了包装。

  1. <Provider> 组件:Redux Store 注入整个 React 应用,使所有子组件可以访问 Store。
  2. usSelector Hook:从 Store 中获取状态,并自动订阅状态更新,当状态变化时,若返回的值与之前不同,组件会重新渲染。
  3. useDispatch Hook:获取 dispatch 方法,派发 Action
  4. connect 高阶组件(类组件兼容):。
import { connect } from 'react-redux';
import { increment, decrement } from './actions';class Counter extends React.Component {render() {const { count, increment, decrement } = this.props;return (<div><button onClick={decrement}>-</button><span>{count}</span><button onClick={increment}>+</button></div>);}
}// 映射 State 到 Counter的 props,以供取值
const mapStateToProps = (state) => ({count: state.count,
});// 映射 dispatch 到 Counter的 props,以供调用
const mapDispatchToProps = {increment,decrement,
};export default connect(mapStateToProps, mapDispatchToProps)(Counter);

connect :同 useSelector作用一样,为了访问 redux的store

但是这个比较绕一点(兼容了类组件)

  • 输入:一个 React 组件(类 or FC)
  • 输出:一个新的组件,该组件能访问 Redux store
// 模拟 react-redux 的 connect 函数
const connect = (mapStateToProps, mapDispatchToProps) => (WrappedComponent) => {return class Connect extends React.Component {static contextType = ReactReduxContext; // 从 Provider 获取 storeconstructor(props, context) {super(props);this.store = context.store;this.state = {mappedProps: this.calculateProps()};}componentDidMount() {this.unsubscribe = this.store.subscribe(() => {const newMappedProps = this.calculateProps();// 浅比较优化,避免不必要的渲染if (!shallowEqual(this.state.mappedProps, newMappedProps)) {this.setState({ mappedProps: newMappedProps });}});}componentWillUnmount() {this.unsubscribe();}calculateProps() {const state = this.store.getState();const stateProps = mapStateToProps(state);const dispatchProps = mapDispatchToProps(this.store.dispatch);return { ...stateProps, ...dispatchProps };}render() {return <WrappedComponent {...this.props} {...this.state.mappedProps} />;}};
};

combineReducers

组合多个独立 reducer 的核心工具函数

  • 自动分发 Action:
    当一个 action 被 dispatch 时,combineReducers 会 ​自动将该 action 传递给所有子 reducer
import { combineReducers } from 'redux'import FatherAndSonReducer from './FatherAndSonReducer'
import TaskReducer from './TaskReducer'const rootReducer = combineReducers({FatherAndSonReducer,TaskReducer
})export default rootReducer
http://www.dtcms.com/wzjs/358994.html

相关文章:

  • 五大门户网站分别是seo推广排名软件
  • 常州做网站找哪家好网络服务公司经营范围
  • 字幕如何做模板下载网站北京seo的排名优化
  • 淘宝联盟怎么做自己的网站seo专业培训需要多久
  • 电子商务网站建设教程免费的黄冈网站代码
  • 做视频网站该把视频文件传到哪seo谷歌外贸推广
  • 湖北网站建设 鄂 icp自媒体十大平台
  • 定制手机软件郑州网站seo外包公司
  • 中国最厉害的公关人seo伪原创工具
  • 建网站程序怎么写semen是什么意思
  • 网站建设 汇卓百度一下就知道
  • 太原关键词排名提升seo外链优化方法
  • 做论坛网站数据库需多大热搜词排行榜关键词
  • 专业营销型网站建设优化软件刷排名seo
  • 一般企业网站建设合同搜索引擎排名优化包括哪些方面
  • 哪种类型的网站比较难做经典广告
  • 郑州做网站优化郑州seo优化外包公司
  • 怎么做网站里的悬浮窗口郑州整站网站优化
  • 服务器关闭 网站被k网络营销的发展趋势
  • 手机网站建设yu名优网站关键词优化
  • 网站关键词检测南宁seo推广优化
  • 免费搭建企业网站电子商务seo名词解释
  • 杭州网站网络 科技公司厦门人才网招聘官网
  • 网站营售中国十大网络营销平台
  • 手机浏览器网站开发工具石家庄百度推广优化排名
  • 保定网站优化百度推广优化中心
  • 网站制作团队数据分析培训班
  • 怎么做网站8uftp极速建站网站模板
  • 互联网保险平台排名网站seo源码
  • 商贸有限公司网站建设lol今日赛事直播