- react 介绍 和 想法A declarative, efficient, and flexible JavaScript library for building user interfacesreact是一个专注于UI的库状态机 输入 => 组件 => 输出组件化 react组件映射 为原生android组件 原生ios 组件 react vr2. jsx 语法JSX就是Javascript和XML结合的一种格式,要使用需要在babelrc里配置, Babel 转译器会把 JSX 转换成一个名为 React.createElement() 的方法调用// 最外层必须有一个元素包裹 <div>hello world!</div> // 属性都要驼峰 <div className=“haha” ></div>// 样式 <div style={{ marginTop: ‘10px’}}></div>// 变量 <div> {user.name }</div>// 事件 <button onClick={}> click me </button>// 遍历 <ul> { list.map( ({name, value}) => <li key={name} value={value}>{name}</li> ) }</ul>// 展开对象 const props = {name: “tom” }<div {…props}></div>3 虚拟DOM 和 diff 算法a. 虚拟DOM(Virtual DOM)机制:对于每一个组件,React会在内存中构建一个相对应的DOM树,基于React开发时所有的DOM构造都是通过虚拟DOM进行,每当组件的状态发生变化时,React都会重新构建整个DOM数据,然后将当前的整个DOM树和上一次的DOM树进行对比,得出DOM结构变化的部分(Patchs),然后将这些Patchs 再更新到真实DOM中b. 两个不同类型的元素会产生不同的树(根元素不同结构树一定不同)c. 开发者可以通过key属性指定不同树中没有发生改变的子元素d. diff算法的核心就是同级比较4. state 和 propsreact 数据是单向流动的 数据自顶向下流动 ,props是传递来的参数,从父级组件向子组件传递的数据, 是只读的state是自己的内部状态在react更新生命周期setState会导致死循环// 默认参数Main.defaultProps = { list: [ ]}// setState 是异步的this.setState( (prevState,props) => ({ text: prev.text + “-ha”}))5. 生命周期Note: 父子组件的挂载顺序,更新顺序6 函数式编程函数式编程,函数作为一等公民,而不是类和对象纯函数 一个函数的返回结果只依赖于它的参数,并且在执行过程里面没有副作用,我们就把这个函数叫做纯函数高阶函数 函数的参数可以是函数,返回值也可以是函数 , 如数组的forEach map filter some reduce ,setTimeout setInterval等柯里化是指这样一个函数(假设叫做createCurry),他接收函数A作为参数,运行后能够返回一个新的函数。并且这个新的函数能够处理函数A的剩余参数6 无状态组件顾名思义,它没有state,接收props,它是一种只负责展示的纯组件 使用函数式的方式声明,会使得代码的可读性更好,并能大大减少代码量,多写无状态组件function HelloComponent(props) { return <div>Hello {props.name}</div>}ReactDOM.render(<HelloComponent name=“marlon” />, mountNode)7 使用 fragment 碎片Jsx 要求返回的元素,必须有东西包裹,使用碎片可以减少一层DOM<React.Fragment> <td>Hello</td> <td>World</td></React.Fragment>// 可以简写为 <><td>Hello</td><td>World</td></>8 使用contextContext 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性,React.createContext 创建一个context,一个context包含provider(数据提供者), comsumer(数据消费者), Provider 有一个value参数,用来覆盖创建时的默认值// 创建一个 theme Context, 默认 theme 的值为 lightconst ThemeContext = React.createContext (’light’);function ThemedButton(props) { // ThemedButton 组件从 context 接收 theme return ( <ThemeContext.Consumer> {theme => <Button {…props} theme={theme} />} </ThemeContext.Consumer>);}// 中间组件function Toolbar(props) { return ( <div> <ThemedButton /> </div>);}class App extends React.Component { render() { return ( <ThemeContext.Provider value=“dark”> <Toolbar /> </ThemeContext.Provider> ); }}9. mobx推荐一个react模块的目录结构/states 状态/(widgets|components)各类组件、弹窗等index.jsindex.lessservice 建议放在config里,全局统一 Computed用于生成计算数据,autorun类似用来监听某一数据改变而作出反映 import {action, observable ,autorun} from ‘mobx’;import StateAdd from “./add"class State { constructor(){ this.$add = new StateAdd(this); } // 显示 @observable show = false; // query @observable query = { trade: null, type: 1 } /** * @name 获取列表 / @action getList = () => { }}const instance = new State();autorun(() => { if(instance.show){ console.log(“打开弹窗了”) }})export default instance10 高阶组件主要有两种实现方式属性proxy、继承实现 通常使用装饰器模式调用,常见的有mobx的 @observer, react-router的withRouter等—— 属性proxy 实现如下 import React from “react"export default class extends React.Component { render = () => <div> <div> <Hoc1_text name={‘Hoc1_text’}/> </div> <div> <Hoc2_text /> </div> </div>}class Text1 extends React.Component { render = () => <div> this is simple text <br/> {this.props.name} </div>}/* * @name 操作props /function Hoc1(Component){ return class extends React.Component { render = () => <div className=‘hoc1’> <Component {…Object.assign({} , this.props, {gen : ‘111’})}/> </div>}}const Hoc1_text = Hoc1(Text1);class Text2 extends React.Component { render = () =><div><input type=“text” value={this.props.value} onChange={this.props.change}/></div>}/* *@name 抽离state */function Hoc2(Component){ return class extends React.Component { state = { value: ‘11’ } change = e => { this.setState({ value: e.target.value }) } render = () => <div> <Component value={this.state.value} change={this.change}/> </div>}}const Hoc2_text = Hoc2(Text2);function Hoc3(Component){ return class extends React.Component { getRef = _ref => { this.refs = _ref; } render = () => <div> <Component ref={this.getRef}/> </div>}}—— 继承组件 实现如下 ——-class Text extends React.Component { render(){ return ( <div> this is text </div> ) }}// 生命周期可以覆盖掉 const hoc2 = Component => { return class NewHoc extends Component { static displayName =
NewHoc-${Component.displayName || Component.name}
render(){ const element= super.render(); console.log(element) const style = { color: element.type === ‘div’ ? ‘red’ : ‘green’ } const newProps = {…this.props, style} return React.cloneElement(element, newProps, element.props.children) } }}const NewCom = hoc2(Text)11 注意事项React组件名字大写不能直接修改state props更新函数里不能做状态操作(死循环)多用无状态组件多用pureComponent React.PureComponent 通过prop和state的浅对比来实现 shouldComponentUpate()。代码清晰,一目了然,注释写好过度封装不如不封装使用 ImmutableJS 处理数据提升性能