React 周边工具

redux

redux 基本概念

reduxreact 的状态管理工具,全局组件可共享 store 的状态。

store

  • 全局的状态管理 store
    所有的 state 都是以一个对象树的形式存在一个单一的 store
  • 唯一改变 state 的办法就是触发 action

reducer

  • 纯函数,产生 newState
    • reducer 就是用来编写专门的纯函数,决定每个 action 如何改变 state
    • 纯函数即没有副作用的函数,不修改输入值,相同的输入一定会有相同的输出
  • dispatch 触发一个 action 的时候,会遍历当前 store 里注册的 reducer

action

  • 对应修改 state 的一个动作

dispatch

  • 通过 dispatch 去触发一个action ,从而修改 state

单向数据流

单向数据流概述

  • dispatch(action)
  • reducer 产生 newState
  • subscribe 触发通知

单向数据流模型

出处:https://coding.imooc.com/lesson/419.html#mid=33927
React 周边工具_第1张图片

react-redux

  • 用于连接 reactredux

provider

  • 通过 react-redux 引入 Provider, 用 Provider 传递 store
import React from 'react';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import todoApp from './reducers';
import App from './components/App';

let store = createStore(todoApp);

export default function () {
    return (<Provider store={store}>
        <App />
    </Provider>);
}

connect

  • 想消费 store,就通过 connectstatedispatch 注入到 props
import { connect } from 'react-redux';

// connect 高阶组件,将 state 和 dispatch 注入到组件 props 中
const VisibleTodoList = connect(
  mapStateToProps,
  mapDispatchToProps
)(TodoList);

export default VisibleTodoList;

mapStateToProps

mapDispatchToProps

中间件 redux-thunk、redux-saga、redux-promise

  • redux 默认只能处理同步 action
  • 如果要支持异步 action,就需要使用中间件

异步 action

// 同步 action
export const addTodo = text => {
	// 返回 action 对象
	return {
		type: 'ADD_TODO',
		id: nextTodoId++,
		text
	};
};
// 异步 action
export const adTodoAsync = text => {
	// 返回函数,其中有 dispatch 参数
	return (dispatch) => {
		// ajax 异步获取数据
		fetch(url).then(res => {
			// 执行异步 action
			dispatch(addTodo(res.text));
		});
	};
};

redux 中间件原理

出处:https://coding.imooc.com/lesson/419.html#mid=33927
React 周边工具_第2张图片

redux 中间件实现

// logger 实现
let next = store.dispatch;

store.dispatch = function dispatchAndLog(action) {
	console..log('dispatching', action);

	next(action);

	console.log('next state', store.getState());
}

react-router

路由模式

  • hash 模式:默认,如 http://abc.com/#/user/10
  • H5 history 模式:需要server 端支持,如 http://abc.com/user/20

基本配置

import React from 'react';
import { HashRouter as Router, Switch, Route } from 'react-router-dom';
import React from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
function RouterComponent() {
	return (
		<Router>
			<Switch>
				<Route exact path="/">
					<Home />
				</Route>
				<Route path="/project/:id">
					<Project />
				</Route>
				<Route path="*">
					<NotFound />
				</Route>
			</Switch>
		</Router>
	);
}

动态路由

function RouterComponent() {
	return (
		<Router>
			<Switch>
				<Route exact path="/">
					<Home />
				</Route>
				<Route path="/project/:id">
					<Project />
				</Route>
				<Route path="*">
					<NotFound />
				</Route>
			</Switch>
		</Router>
	);
}
import React from 'react';
import { Link, useParams } from 'react-router-dom';

function Project() {
	// 获取 url 参数,如 '/project/100'
	const { id } = useparaqms();
	
	console.log('url param id', id);

	return (
		<div>
			<Link to="/">首页</Link>
		</div>
	);
}

配置懒加载

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import React, { Suspense, lazy } from 'react';

const Home = lazy(() => import(';'routes/Home'));
const About = lazy(() => import(';'routes/About'));

const App = () => (
	<Router>
		<Suspense fallback={<div>Loading...</div>}>
		<Switch>
			<Route exact path="/" component={home} />
			<Route path="/about" component={About} />
		/Switch>
	</Router>
);

FQA

  1. reduxaction 如何处理异步?
    • 使用中间件 redux-thunk 或者 redux-saga
  2. redux-thunk 可以带来哪些好处?
    • 没有中间件的时候,dispatch 只能用来触发 reducer 更新 statedispatchaction 只能是一个对象
    • 而有中间件相当于对现有的 dispatch 进行二次封装,加一些自己的逻辑在里面,可以进行异步处理,其实最终还是触发了 reducer 来更新 state;可以 dispatch 一个函数。
  3. 普通的 ajax 请求或者其他异步操作,配合 redux 直接使用,即使不用 thunk,也是可以实现功能的,为什么还要用 redux-thunk
    • 如果用普通的 ajax ,就得放在页面或者 react 组件中触发请求,然后再把请求结果 dispatchstore 中,这样就把数据层拆分了。
    • 从设计原则的角度,数据层应该和 view 层(即 页面或者 React 组件)是分离的,即便没有 view 层,数据层也应该保持独立。
  4. 描述 redux 的单向数据流。
  • View 中触发一个动作,然后 dispatch 一个 action 去执行 reducer,修改 state,然后 subscribe 触发通知去更新 View
  • 加入中间件的话,在 dispatch 的时候可以做一些额外的操作,然后再去触发 action 执行 reducer 修改 state
  1. reducer 为什么必须是一个纯函数?
    • 所谓纯函数就是没有副作用的函数,不改变输入的值,相同的输入一定会有相同的输出。
    • 这是因为 redux 是通过比较一个状态前后是否有改变来决定页面是否更新的,而比较状态是否改变是通过浅层比较的,因为深度比较很耗费性能,所以有效的解决方案就是做一个规定,当无论发生任何变化时,都要返回一个新的对象,没有变化时返回旧的对象。

你可能感兴趣的:(react.js,javascript,前端)