redux与react-redux

本文围绕React与Redux展开,介绍了Redux中Store、State、action等核心概念,如Store是保存数据的容器,State是其快照。还阐述了createStore的实现,以及Context在组件间数据传递的作用。此外,讲解了React - Redux将组件分类,以及connect方法从UI组件生成容器组件的实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Store:

Store是保存数据的地方,可以看成一个容器。整个应用只能有一个 Store。
Redux 提供createStore这个函数,用来生成 Store。
import { createStore } from 'redux';
const store = createStore(fn);
createStore函数接受一个函数作为参数,返回新生成的 Store 对象。

State:

Store对象包含所有数据。state就是某个时刻对 Store 生成的一个快照,通过store.getState()得到:
const state = store.getState();
Redux 中一个 State 对应一个 View。只要 State 相同,View 就相同。

action:

action是一个对象,必须含有type属性,表示action的名称,一般语义化为要做的行为,

store.dispatch(action):

dispatch会将action(行为)发送给store,触发行为

Reducer(state,action):

Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer.
Reducer是一个纯函数,接受 Action 和当前 State 作为参数,返回一个新的 State。

store.subscribe(listener):

store.subscribe方法是设置监听函数,当State 发生变化时就自动执行这个函数。
View的更新函数(对于 React 项目,是组件的render方法或setState方法)放入listen,就会实现 View 的自动渲染。
store.subscribe方法返回一个函数,调用这个函数就可以解除监听。

createStore实现:

const createStore = (reducer)=>{
		let state;
		let list = [];//作为一个容器,保存
		const getState = ()=>{
			return state;
		}
		const subscribe = (fn)=>{
			list.push(fn);
			//	返回一个函数,执行函数时,取消回调函数的执行
			return ()=>{
				list = list.fibter((cb)=>{
					return cb != fn;
				});
			}
		}
		//	dispatch时,有行为action,就会更新state
		const dispatch = ( action )=>{
			state = reducer(state,action);
			list.forEach( (fn)=>{
				fn();
			} );
		}
		return { getState, subscribe, dispatch }
}

Context:

当组件之间嵌套的层级过多时,就需要在每一层级进行传递,而这种传递对日后的维护成本十分巨大,Context 提供了一个无需为每层组件手动添加 props,就能在组件树间进行数据传递的方法。
某些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props(即Context 主要应用场景在于很多不同层级的组件需要访问同样一些的数据。请谨慎使用,因为这会使得组件的复用性变差。):

  1. 为需要多重传递的属性创建一个全局context:const ThemeContext = React.createContext('light'); //light是默认值
  2. 在父组件的 render()函数内写:
    render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
    // 无论多深,任何组件都能读取这个值。
    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。
    	return (
    		//	将此全局context.Provider以标签的形式写在最外围
    		//	将 “dark” 作为要传递的值
      		<ThemeContext.Provider value="dark">
        		<ThemedButton/>    //	子组件
      		</ThemeContext.Provider>
    	);
    }
    
  3. 在子组件中:
    class ThemedButton extends React.Component {
    	// 指定 contextType 读取当前的 theme context。
    	// React 会往上找到最近的 theme Provider,然后使用它的值。
    	// 在这个例子中,当前的 theme 值为 “dark”。
    	//	使用this.context获取到值
    	static contextType = ThemeContext;
    	render() {
    		 return <Button theme={this.context} />;
    	}
    }
    

React-Redux:

React-Redux是React的专用库,实际项目可使用Redux或者React-Redux。
React-Redux将组件分为两类:UI组件和容器组件
其中UI组件(纯组件)只负责UI呈现,不负责业务逻辑,没有状态(this.state),所需数据由this.prop提供,不使用Redux的API。
而容器组件使用Redux的API,带有内部状态,并且容器组件由React-Redux自动生成。
connect方法,从UI组件生成容器组件,借鉴了Conntext的实现思想:即将状态的数据放置在外组件,其API如下:

import {} from 'react-redux'
const mapStateToProps = (state)=>{
	return {
		todos:getVisibleTodos(state.todos,state.visiblityFilter)   	//	getVisibleTodos函数用来计算需要state中的哪些值
		}
}
const mapDispatchToProps = (dispatch)=>{
	return {
		onClickTodo:() =>{    // onClickTodo是UI组件中要被触发的事件,触发后执行dispatch
			dispatch({
				type:'TOGGLE_TODO',
				id
			})
		}
	}
}
const VisibleTodoList = connect(mapStateToProps,mapDispatchToProps)(TodoLIst);

connect函数接受两个函数参数,返回一个函数,返回的函数的参数是UI组件(此处是TodoLIst),该方法会自动生成一个容器组件,并将其连接。
形参mapStateToProps是一个函数,负责将state映射到UI组件的props上,mapStateToProps()接受一个参数state,返回所需要的状态值。
形参mapDispatchToProps也是一个函数,负责将操作逻辑(行为事件)映射到UI组件的Action。mapDispatchToProps()接收dispatch,在事件中执行action.

connect实现:

上面已经分析了connect的功能,接下来根据其功能实现connect函数:

const connect = (mapStateToProps,mapDispatchToProps) => {
	return (WrapperComponent)=>{
		//	定义一个容器包裹UI组件,利用父节点更新会自动更新子组件的特性来自动更新子组件 
		class Connect extends Component{
			componentDidMount(){
				//	利用跨多级组件通信context得到store,此处使用旧的API,w未来会废弃
				const store = this.context.store;
				this.unsubscribe = store.subscribe(()=>{
					this.forceUpdate();
				});
			}
			componentWillUnmount(){
				this.unsubscribe();
			}
			//	以上代码实现自己更新自己的功能。
			render(){
				const store = this.context.store;
				const stateProps = mapStateToProps(store.getState());	//返回当前需要的属性
				const dispatchProps = mapDispatchToProps(store.dispatch);		//	返回当前所需的方法
				const props = Object.assign({},stateProps,dispatchProps);
				return React.createElement(WrapperComponent,props);	    //	创建UI组件的ReactDom节点,并将数据函数传入UI组件的props
			}
		}
		Connect.contextTypes = {
			store:React.PropTypes.object
		}
		return Connect;
	}
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值