开头语:纸上得来终觉浅,绝知此事要躬行!
- 一.组件
- 函数式定义的无状态组件
- es5原生方式React.createClass定义的组件
- es6形式的extends React.Component定义的组件
React.Component是以ES6的形式来创建react的组件的,是React目前极为推荐的创建有状态组件的方式,最终会取代React.createClass形式;相对于 React.createClass可以更好实现代码复用。
- 二.state
1.state的作用
state是React中组件的一个对象.React把用户界面当做是状态机,想象它有不同的状态然后渲染这些状态,可以轻松让用户界面与数据保持一致.
React中,更新组件的state,会导致重新渲染用户界面(不要操作DOM).简单来说,就是用户界面会随着state变化而变化.
2.state工作原理
常用的通知React数据变化的方法是调用setState(data,callback).这个方法会合并data到this.state,并重新渲染组件.渲染完成后,调用可选的
callback回调.大部分情况不需要提供callback,因为React会负责吧界面更新到最新状态.
3.那些组件应该有state?
大部分组件的工作应该是从props里取数据并渲染出来.但是,有时需要对用户输入,服务器请求或者时间变化等作出响应,这时才需要state.
组件应该尽可能的无状态化,这样能隔离state,把它放到最合理的地方(Redux做的就是这个事情?),也能减少冗余并易于解释程序运作过程.
常用的模式就是创建多个只负责渲染数据的无状态(stateless)组件,在他们的上层创建一个有状态(stateful)组件并把它的状态通过props
传给子级.有状态的组件封装了所有的用户交互逻辑,而这些无状态组件只负责声明式地渲染数据.
- 三.props
组件中的props是一种父级向子级传递数据的方式.
state 和 props 主要的区别在于 props 是不可变的,而 state 可以根据与用户交互来改变。这就是为什么有些容器组件需要定义 state 来更新和修改数据。 而 子组件只能通过 props 来传递数据。
class Welcome extends React.Component { render() { return <h1>hello::{this.props.name},{this.props.name2}</h1> } } class Divs extends React.Component { render() { return ( <div> <Welcome name='lili11' name2='kk11'/> <Welcome name='lili22' name2='kk222'/> <Welcome name='lili33' name2='kk443'/> </div> ); } } var element = <Divs/>; ReactDOM.render(element, document.getElementById('root'));
- 四.事件
当然,React.Component有三种手动绑定方法:可以在构造函数中完成绑定,也可以在调用时使用method.bind(this)来完成绑定,还可以使用arrow function来绑定。其绑定可以有:
{ constructor(props) { super(props); this.handleClick = this.handleClick.bind(this); //构造函数中绑定 } <div onClick={this.handleClick.bind(this)}></div> //使用bind来绑定 <div onClick={()=>this.handleClick()}></div> //使用arrow function来绑定
Redux 是 JavaScript 状态容器,提供可预测化的状态管理。
安装: npm install --save redux
安装React绑定库和开发者工具:npm install --save react-redux;
npm install --save-dev redux-devtools
Redux 三大原则
单一数据源:整个应用的state被储存在一棵 object tree 中,并且这个 object tree 只存在于唯一一个store 中。
State只读:惟一改变 state 的方法就是触发 action,action 是一个用于描述已发生事件的普通对象。
使用纯函数来执行修改:通过编写reducers实现,reducer只是一些纯函数,接收state和action,返回新的state。
Action
Action 是把数据从应用(译者注:这里之所以不叫 view 是因为这些数据有可能是服务器响应,用户输入或其它非 view 的数据 )传到 store 的有效载荷。它是 store 数据的唯一来源。一般来说你会通过 store.dispatch()
将 action 传到 store。
1 export const ADD_ITEM = 'ADD_ITEM'; 2 export function addItem(text) { 3 return {type: ADD_ITEM, text} 4 }
Reducer
在 Redux 应用中,所有的 state 都被保存在一个单一对象中,Reducer就是用来更新state
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
import {combineReducers} from 'redux' import {ADD_ITEM, DELETE_ITEM, CHANGE_VALUE,GET_VALUE} from './actions' function todos(state = [], action) { switch (action.type) { case ADD_ITEM: return [ ...state, { text: action.text, completed: false } ] case DELETE_ITEM: // dodelete return state; default : return state } } |
Store
Store 就是把它们联系到一起的对象。Store 有以下职责:
- 维持应用的 state;
- 提供
getState()
方法获取 state; - 提供
dispatch(action)
方法更新 state; - 通过
subscribe(listener)
注册监听器; - 通过
subscribe(listener)
返回的函数注销监听器。
再次强调一下 Redux 应用只有一个单一的 store。当需要拆分数据处理逻辑时,你应该使用 reducer 组合 而不是创建多个 store。
1
2
|
const operationApp = combineReducers({todos, value}) export default operationApp; |
使用
index.js中
1
2
3
4
5
6
7
8
|
let store = createStore(todoApp) let rootElement = document.getElementById( 'root' ) render( <Provider store={store}> <ToDo /> </Provider>, rootElement ) |
Todo.Js中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
const { dispatch,todos,value,store} = this .props; return ( <div> <MuiThemeProvider> <Paper style={style} zDepth={3}> <div className= "todo-wrap" > <div style={divstyle}> <TodoHeader className= "todoHeader" addTodo={text=>dispatch(addItem(text))} curValue={value} valueChange={text=>dispatch(valueChange(text))}/> </div> </div> </Paper> </MuiThemeProvider> </div> ); } function select (state) { return { todos: state.todos, value: state.value } } export default connect( select )(ToDoApp); |