事件处理 1,注意事项
React事件绑定属性的命名采用驼峰式写法,而不是小写。
如果是用jsx的语法需要穿一个函数作为事件处理函数,而不是一个字符串
1 2 3 <button onClick={activateLasers}> Activate Lasers </button>
在 React 中另一个不同是你不能使用返回 false 的方式阻止默认行为。你必须明确的使用 preventDefault。
1 2 3 4 5 6 7 8 9 10 11 function ActionLink ( ) { function handleClick (e ) { e.preventDefault (); console .log ('The link was clicked.' ); } return ( <a href ="#" onClick ={handleClick} > Click me </a > ); }
ES6 class语法定义组件,事件处理器会成为类的一个方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class Toggle extends React.Component { constructor (props ) { super (props); this .state = {isToggleOn : true }; this .handleClick = this .handleClick .bind (this ); } handleClick ( ) { this .setState (prevState => ({ isToggleOn : !prevState.isToggleOn })); } render ( ) { return ( <button onClick ={this.handleClick} > {this.state.isToggleOn ? 'ON' : 'OFF'} </button > ); } }
2,向事件处理程序传递参数
下面两种方式是等价的,分别通过 arrow functions 和 Function.prototype.bind 来为事件处理函数传递参数。
1 2 <button onClick={(e ) => this .deleteRow (id, e)}>Delete Row </button> <button onClick ={this.deleteRow.bind(this, id )}> Delete Row</button >
箭头函数必须显示传递e, bind方式要隐示传递
通过bind 方式向监听函数传参,在类组件中定义的监听函数,事件对象 e 要排在所传递参数的后面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class Popper extends React.Component { constructor ( ){ super (); this .state = {name :'Hello world!' }; } preventPop (name, e ){ e.preventDefault (); alert (name); } render ( ){ return ( <div > <p > hello</p > {/* Pass params via bind() method. */} <a href ="https://reactjs.org" onClick ={this.preventPop.bind(this,this.state.name)} > Click</a > </div > ); } }
Redux 1, 介绍
Store
State
Action
Action Creator
store.dispatch()
Reducer
store.subscribe()
2, 工作流程
然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。
1 let nextState = todoApp (previousState, action);
State 一旦有变化,Store 就会调用监听函数。
1 store.subscribe (listener)
可以通过store.getState()得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。
1 2 let newState = store.getState ();component.setState (newState);
参考[http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html]
3,组件拆分和react-redux、Provider、connect(连接器)
在组件开发中,按职责我们可以划分:容器类组件、展示类组件,前者负责从state获取属性,后者负责渲染界面和自身的状态控制。
react-redux 为 React 组件和 Redux 提供的 state 提供了连接。当然可以直接在 React 中使用 Redux:在最外层容器组件中初始化 store,然后将 state 上的属性作为 props 层层传递下去。但是这样并是我们推荐的状态管理方式。
1 2 3 4 5 6 7 8 9 10 class App extends Component{ componentWillMount(){ store.subscribe((state)=>this.setState(state)) } render(){ return <Comp state={this.state} onIncrease={()=>store.dispatch(actions.increase())} onDecrease={()=>store.dispatch(actions.decrease())}/> } }
我们推荐的方式是react-redux:1,内容组件最外层包裹Provider,将之前创建的store作为prop传给Provider。Provider接收redux的createStore()的结果,并且放到context里,让子组件可以通过context属性直接获取到这个createStore的结果。且返回一个与store连接后的容器组件。2,Provider内的任何一个组件,如果需要使用state中的数据,就必须是「被 connect 过的」组件——使用connect方法对当前内容组件包装后的产物,connect会返回一个与store连接后的新组件。3,connect会返回一个与store连接后的新组件。会接收到mapStateToProps,会在内部subscribe全局state的改变,来判断props是否更改,如果需要更新,才触发更新。
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 29 30 31 32 33 34 35 36 37 38 39 import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; import * as dictActions from '../../actions/dict'; class DictPage extends Component { constructor(props){ super(props); } componentWillMount(){ const { getDictsResult } = this.props; getDictsResult({ q: 'good', lang: 'en' }) } componentDidMount(){ const { dict } = this.props; } render() { return (<div>xxxxx</div>); } } //创建输入逻辑mapStateToProps,是store、state映射 function mapStateToProps(state) { return { dict: state.dict.data.data }; } //输出逻辑mapDispatchToProps,是dispatch映射 function mapDispatchToProps(dispatch) { return bindActionCreators(dictActions, dispatch); } //把容器组件和ui组件结合导出 export default connect(mapStateToProps, mapDispatchToProps)(DictPage);
参考例子
React-router(v4版本) 1, 包的选择
浏览器用的router在react-router-dom里。所以浏览器里使用的时候只需要import react-router-dom就可以。react-router-native供React Native应用使用。
2,路由不在集中存放一起,可以和Ui组件放在一起,成为组件的一部分。 3,包含式路由与exact
如匹配 path=”/users” 的路由会匹配 path=”/“的路由,在页面中这两个模块会同时进行渲染,所以就多了exact。
4,独立路由Switch
采用Switch 只有一个路由会被渲染,并且总是渲染第一个匹配到的组件。
5,link
to(string / object):要跳转的路径或地址;
replace :为 true 时,点击链接后将使用新地址替换掉访问历史记录里面的原地址。反之不会替换记录,默认为false。
NavLink :是 的一个特定版本,会在匹配上当前URL的时候会给已经渲染的元素添加样式参数。
6,异步加载路由和模块
7, 手动控制路由的跳转
使用 withRouter高阶组件,提供了history让你使用
1 2 3 4 5 6 7 8 9 10 11 12 import React from "react"; import {withRouter} from "react-router-dom"; class MyComponent extends React.Component { ... myFunction() { this.props.history.push("/some/Path"); } ... } const MyComponent=withRouter(connect(mapStateToProps,mapDispatchToProps)(MyComponent)) export default MyComponent;
使用Context,在Router组件中通过Contex暴露了一个router对象。context增加了耦合难度尽量少用或者用在全局登录状态、颜色等等。
1 2 3 4 5 6 7 8 9 10 11 12 13 import React from "react"; import PropTypes from "prop-types"; class MyComponent extends React.Component { static contextTypes = { router: PropTypes.object } ... myFunction() { this.context.router.history.push("/some/Path"); } ... }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 import React from "react"; import { push } from 'react-router-redux' import PropTypes from "prop-types"; class MyComponent extends React.Component { static contextTypes = { store: PropTypes.object } ... myFunction() { this.context.store.dispatch(push('path')) } ... }
constructor(super(props)) constructor( )——构造方法
ES6对类的默认方法,new命令生成实例自动调用,如果没有显示定义会默认添加空的constructor方法。
es5没有继承写法,通过prototype来达到目的。
1 2 3 4 5 6 7 8 //构造函数People function People (name,age){ this.name = name; this.age = age } People.prototype.sayName = function(){ return '我的名字是:'+this.name; }
1 2 3 4 5 6 7 8 9 10 11 class People{ //构造方法constructor就等于上面的构造函数People constructor(name,age){ this.name = name; this.age = age; } sayName(){ return '我的名字是:'+this.name; } }
super() – 继承。
子类是没有自己的this对象的,它只能继承自父类的this对象,然后对其进行加工,而super( )就是将父类中的this对象继承给子类的。没有super,子类就得不到this对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 class People{ constructor(name,age){ this.name = name; this.age = age; } sayName(){ return '我的名字是:'+this.name; } } class har extends People{ constructor(name,age,sex){ super(name,age);//调用父类的constructor(name,age) this.sex = sex; } haha(){ return this.sex + ' ' + super.sayName();//调用父类的sayName() } }
es5 new
1.生成一个空的对象并将其作为 this;
2.将空对象的 proto 指向构造函数的 prototype;
3.运行该构造函数;
4.如果构造函数没有 return 或者 return 一个返回 this 值是基本类型,则返回this;如果 return 一个引用类型,则返回这个引用类型。
es5和es6继承机制区别
es5先创建子类的实例对象this,然后再将父类的方法添加到this上( Parent.apply(this) )
ES6采用的是先创建父类的实例this(故要先调用 super( )方法),完后再用子类的构造函数修改this
学习文章参考