第六章 React UI
一、流行的开源 React UI 组件库
1. material-ui(国外)
- 官网: http://www.material-ui.com/#/
- github: https://github.com/callemall/material-ui
2. ant-design(国内蚂蚁金服)
- 官网: https://ant.design/index-cn
- Github: https://github.com/ant-design/ant-design/
- 使用:npm install antd
二、代码
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(<App />, document.getElementById("root"));
antd 的基本使用
import React, { Component } from "react";
import { Button, DatePicker } from "antd";
import {
WechatOutlined,
WeiboOutlined,
SearchOutlined,
} from "@ant-design/icons";
const { RangePicker } = DatePicker;
export default class App extends Component {
render() {
return (
<div>
App....
<button>点我</button>
<Button type="primary">Button1</Button>
<Button>Button2</Button>
<Button type="link">Button3</Button>
<Button type="primary" icon={<SearchOutlined />}>
Search
</Button>
<WechatOutlined />
<WeiboOutlined />
<DatePicker />
<RangePicker />
</div>
);
}
}
第七章 redux
一、redux 理解
1. 学习文档
- 英文文档: https://redux.js.org/
- 中文文档: http://www.redux.org.cn/
- Github: https://github.com/reactjs/redux
2. redux 是什么
- redux 是一个专门用于做状态管理的 JS 库(不是 react 插件库)。
- 它可以用在 react, angular, vue 等项目中, 但基本与 react 配合使用。
- 作用: 集中式管理 react 应用中多个组件共享的状态。
3. 什么情况下需要使用 redux
- 某个组件的状态,需要让其他组件可以随时拿到(共享)。
- 一个组件需要改变另一个组件的状态(通信)。
- 总体原则:能不用就不用, 如果不用比较吃力才考虑使用。
4. redux 工作流程
二、redux 的三个核心概念
1. action
- 动作的对象
- 包含 2 个属性
- type:标识属性, 值为字符串, 唯一, 必要属性
- data:数据属性, 值类型任意, 可选属性
- 例子:{ type: ‘ADD_STUDENT’,data:{name: ‘tom’,age:18} }
2. reducer
- 用于初始化状态、加工状态。
- 加工时,根据旧的 state 和 action,产生新的 state 的纯函数。
3. store
- 将 state、action、reducer 联系在一起的对象
- 如何得到此对象?
- import {createStore} from ‘redux’
- import reducer from ‘./reducers’
- const store = createStore(reducer)
- 此对象的功能?
- getState(): 得到 state
- dispatch(action): 分发 action, 触发 reducer 调用, 产生新的 state
- subscribe(listener): 注册监听, 当产生了新的 state 时, 自动调用
三、redux 的核心 API
1. createstore()
- 作用:创建包含指定 reducer 的 store 对象
2. store 对象
- 作用: redux 库最核心的管理对象
- 它内部维护着:
- 核心方法
- getState()
- dispatch(action)
- subscribe(listener)
- 具体编码
- store.getState()
- store.dispatch({type:‘INCREMENT’, number})
- store.subscribe(render)
3. applyMiddleware()
4. combineReducers()
四、使用 redux 编写应用
1. 效果
2. 纯 react 版
2.1 App
import React, { Component } from "react";
import Count from "./components/Count";
export default class App extends Component {
render() {
return (
<div>
<Count />
</div>
);
}
}
2.2 Count
import React, { Component } from "react";
export default class Count extends Component {
state = { count: 0 };
increment = () => {
const { value } = this.selectNumber;
const { count } = this.state;
this.setState({ count: count + value * 1 });
};
decrement = () => {
const { value } = this.selectNumber;
const { count } = this.state;
this.setState({ count: count - value * 1 });
};
incrementIfOdd = () => {
const { value } = this.selectNumber;
const { count } = this.state;
if (count % 2 !== 0) {
this.setState({ count: count + value * 1 });
}
};
incrementAsync = () => {
const { value } = this.selectNumber;
const { count } = this.state;
setTimeout(() => {
this.setState({ count: count + value * 1 });
}, 500);
};
render() {
return (
<div>
<h1>当前求和为:{this.state.count}</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>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
);
}
}
3. redux 精简版
3.1 store
import { createStore } from "redux";
import countReducer from "./count_reducer";
export default createStore(countReducer);
3.2 count_reducer
const initState = 0;
export default function countReducer(preState = initState, action) {
const { type, data } = action;
switch (type) {
case "increment":
return preState + data;
case "decrement":
return preState - data;
default:
return preState;
}
}
3.3 Count
import React, { Component } from "react";
import store from "../../redux/store";
export default class Count extends Component {
increment = () => {
const { value } = this.selectNumber;
store.dispatch({ type: "increment", data: value * 1 });
};
decrement = () => {
const { value } = this.selectNumber;
store.dispatch({ type: "decrement", data: value * 1 });
};
incrementIfOdd = () => {
const { value } = this.selectNumber;
const count = store.getState();
if (count % 2 !== 0) {
store.dispatch({ type: "increment", data: value * 1 });
}
};
incrementAsync = () => {
const { value } = this.selectNumber;
setTimeout(() => {
store.dispatch({ type: "increment", data: value * 1 });
}, 500);
};
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>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
);
}
}
3.4 index
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
import store from "./redux/store";
ReactDOM.render(<App />, document.getElementById("root"));
store.subscribe(() => {
ReactDOM.render(<App />, document.getElementById("root"));
});
3.5 总结
(1).去除Count组件自身的状态
(2).src下建立:
-redux
-store.js
-count_reducer.js
(3).store.js:
1).引入redux中的createStore函数,创建一个store
2).createStore调用时要传入一个为其服务的reducer
3).记得暴露store对象
(4).count_reducer.js:
1).reducer的本质是一个函数,接收:preState,action,返回加工后的状态
2).reducer有两个作用:初始化状态,加工状态
3).reducer被第一次调用时,是store自动触发的,
传递的preState是undefined,
传递的action是:{type:'@@REDUX/INIT_a.2.b.4}
(5).在index.js中监测store中状态的改变,一旦发生改变重新渲染<App/>
备注:redux只负责管理状态,至于状态的改变驱动着页面的展示,要靠我们自己写。
4. redux 完整版
4.1 store
import { createStore } from "redux";
import countReducer from "./count_reducer";
export default createStore(countReducer);
4.2 constant
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'
4.3 count_action
import { INCREMENT, DECREMENT } from "./constant";
export const createIncrementAction = (data) => ({ type: INCREMENT, data });
export const createDecrementAction = (data) => ({ type: DECREMENT, data });
4.4 count_reducer
import {INCREMENT, DECREMENT} from './constant'
const initState = 0;
export default function countReducer(preState = initState, action) {
const { type, data } = action;
switch (type) {
case INCREMENT:
return preState + data;
case DECREMENT:
return preState - data;
default:
return preState;
}
}
4.5 Count
import React, { Component } from "react";
import store from "../../redux/store";
import {createDecrementAction, createIncrementAction} from '../../redux/count_action'
export default class Count extends Component {
increment = () => {
const { value } = this.selectNumber;
store.dispatch(createIncrementAction(value*1));
};
decrement = () => {
const { value } = this.selectNumber;
store.dispatch(createDecrementAction(value*1) );
};
incrementIfOdd = () => {
const { value } = this.selectNumber;
const count = store.getState();
if (count % 2 !== 0) {
store.dispatch(createIncrementAction(value*1));
}
};
incrementAsync = () => {
const { value } = this.selectNumber;
setTimeout(() => {
store.dispatch(createIncrementAction(value*1));
}, 500);
};
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>
<button onClick={this.decrement}>-</button>
<button onClick={this.incrementIfOdd}>当前求和为奇数再加</button>
<button onClick={this.incrementAsync}>异步加</button>
</div>
);
}
}
4.6 总结
新增文件:
1.count_action.js 专门用于创建action对象
2.constant.js 放置容易写错的type值