React框架学习
开头语:纸上得来终觉浅,绝知此事要躬行!
- 一.组件
- 函数式定义的无状态组件
- 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;
-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);
|