前端学习笔记(一)——React框架

前段时间学习了有关React框架,做了一份笔记,记录并分享一下。以便后续方便查找和使用。

PS:这份笔记只是记录了本人在学习过程中,认为React中比较重要的点进行了记录,详细的知识点还需要深入去探讨研究

***欢迎指出错误或不当的地方***


  • React专注视图层,特点:Virtual DOM;函数式编程;JSX;单向数据流

  • JSX基本语法:DOM元素中有两个属性特殊,class和for(JS中的关键字),需要转换为className和htmlFor

  • Web Component(Web组件)

创建React组件的三种方法

①React.createClass,方法传入的参数是一个对象

React.createClass({
    getDefaultProps(){
        //初始化props
        return {};
    },
    getInitialState(){
        //初始化state
        return {};
    },
    render(){
        return (
            <div>Hello World!</div>
        )
    }
}) 
②ES6 Class,常用的创建方式
class XXX extends React.Component{
    static propType = {};//props的类型检查
    static defaultProps = {};//默认的props
    constructor(props){
        //构造函数,state初始在这里设置
        super(props);
        this.state = {};
    }
    //生命周期方法
    //...
    //render
    render(){
        //render里不能调用this.setState
        //有逻辑判断的例外
        return (
            <div>Hello World!</div>
        )
    }
}

③无状态函数,可以传入props和context,无state,无生命周期,但propTypes和defaultProps可以通过静态方法设置

function XXX(props){
    return (
        <div {...props}>Hello World</div>
    )
}
XXX.propTypes = {};
XXX.defaultProps = {};
  • 生命周期(按顺序)

构建时:getDefaultProps(第一次构建该组件时)、getInitialState、componentWillMount、render、componentDidMount

更新时(props和state修改时):componentWillReceiveProps(props改变时才有这个)、shouldComponentUpdate、componentWillUpdate、render、componentDidUpdate

卸载时:componentWillUnmount

注意:生命周期方法中,只有componentWillMount、componentDidMount、componentDidUpdate、componentWillReceiveProps才能调用this.setState,其余的会造成调用循环,导致浏览器崩溃


  • propType

从React v15.5开始,React.PropTypes助手函数已经被弃用,建议使用prop-types库来定义类型

import PropTypes from 'prop-types';
//PropTypes
//类型包括array/bool/func/number/object/string/symbol
//以及node/element/instanceOf()/one of(['',''])/oneOfType([])/arrayOf()/objectOf()/shape()

具体可以去prop-types库或者propTypes类型检查


  • React数据流

state

props:有一个内置的prop——children


  • ReactDOM

ReactDOM功能是将组件渲染到真实DOM上。API有findDOMNode、unmountCpmponentAtNode、render。

还有个unstable_renderSubtreeIntoContainer方法可以了解一下


  • refs引用

组件被调用时,会新建一个该组件的实例,refs就会指向这个实例。

如果放在原生DOM中,就会返回DOM节点;如果放在React组件中,就返回该组件的实例

支持回调函数以及字符串两个格式。

①回调函数

//挂载到实例的myInput属性上
<input type='text' ref={(ref) => this.myInput = ref}/>

②字符串

//声明
<MyInput ref='myInput' />

//调用,并获取对应的DOM
const myInput = this.refs.myInput;
const inputDOM = ReactDOM.findDOMNode(myInput);

  • React事件系统——合成事件

事件委派:并不会把所有事件绑定到真实节点,而是绑定到结构的最外层,再用一个事件监听器,维持一个映射来保存所有组件的事件监听和处理函数。

在使用ES6 Class或者纯函数创建组件时,需要手动绑定this。

①bind

handleClick(e,arg){
    //...
}
render(){
    return <button onClick={this.handleClick.bind(this,'test')}>test</button>
}

②构造器内声明

constructor(props){
    super(props);
    this.handleClick = this.handleClick.bind(this);
 }

handleClick(e){
    //...可以调用this.setState
}

③箭头函数

handleClick(){
    //...
};
render(){
    return <button onClick={() => this.handleClick()}>test</button>
}

注意:React合成事件最好不要与原生事件混用。阻止React事件冒泡的行为只能用于合成事件系统,无法阻止原生事件冒泡;相反,原生事件的阻止冒泡行为,可以阻止React合成事件的传播。

React事件与原生事件比较

①事件传播和阻止事件传播

React仅支持事件冒泡(IE9以下不支持事件捕获)

阻止原生事件传播:e.stopPropagation();或者e.cancelBubble= true;(IE9以下)

React阻止事件传播:e.stopPropagation();

②事件类型

React合成事件的类型是原生事件的一个子集

③绑定方式

原生的JS绑定有三种:

//绑定在DOM对象上
ele.click = function(){}
//addEventListener或者attachEvent
ele.addEventListener('click',function(){},false);
ele.attachEvent('click',function(){})
//绑定在DOM节点上
<button οnclick='alert(test)'>test</button>

React绑定事件:

<button onClick={this.handleClick}>test</button>

④事件对象

原生事件在低版本需要用window.event来获取事件对象,React则直接得到一个合成事件对象


  • 样式处理

可以用classname库或者CSS Modules


  • 组件间通信

父→子:通过props传递子组件需要的信息。

子→父:通过回调函数;自定义事件机制。

跨级组件(有嵌套关系的跨级):推荐使用高阶组件来实现。(也可以用context来实现,不推荐,因为层次复杂时,无法知道centext从哪里传来

没有嵌套关系的组件:借用NodeJS的Events模块

import { EventEmitter } from 'events';

注意,在组件完成挂载后在订阅事件,卸载时取消事件订阅;


  • 高阶组件

概念:接受一个组件作为输入,输出一个新的组件。

好处:使代码复用性、逻辑性、抽象特性提高,可以劫持render方法,也可以控制props和state

实现方式:

①属性代理

const MyContainer = (WrappedComponent) => 
    class extends Component {
        render(){
            const newProps = {
                text : 'higher-order component'
            }
            return < WrappedComponent {…this.props} {…newProps}/>
        }
    }

生命周期方法:挂载(componentDidMount)从内到外执行,卸载(componentWillUnmount)从外到内执行

特性:①控制props②通过refs使用引用③抽象state(关于容器组件和UI组件)④使用其他元素包裹WrappedComponent:既可以加样式、也可以实现布局

②反向继承

const MyContainer = (WrappedComponent) => 
    class extends WrappedComponent {
        render(){
            return super.render();
        }
    }

特点:①渲染劫持②控制state


  • 组件性能优化

①纯函数。特点:相同输入总是返回相同输出;没有副作用;无额外状态依赖

②PureRender。

Immutable Data

是一旦创建就不能再修改的数据。(结构共享:若树一个节点变化,只修改这个节点和受影响的父节点,其他节点共享)

优点:

1) 降低可变带来的复杂度,数据难被回溯

2) 节省内存

3) 撤销/重做,复制/黏贴甚至时间旅行做起来很简单

4) 并发安全

5) 符合函数式编程

④key prop:标记动态子组件,在Virtual DOM作diff时有优化效果

⑤react-addons-perf


  • 动画(待更新)

  • setState异步更新

setState通过队列机制实现state更新。调用后,不会立即更新state,而是合并state后放入状态队列,队列机制进行批量更新。注意循环调用风险;更多细节可以去了解一下源码。


  • Virtual DOM(虚拟DOM

Virtual DOM的节点称为ReactNode,有三种类型ReactElement、ReactFragment和ReactText

ReactElement又分为ReactComponentElement和ReactDOMElement

diff算法

三个优化策略:

①  web UI中DOM节点跨级移动操作少,忽略不计

Virtual DOM只会对同级的DOM节点进行比较,即同个父节点下的所有子节点。

②  拥有相同类的两个逐渐会生成相似的树形结构,不同类生成不同的树形结构

③  对于同一层级的一组子组件,他们可以通过唯一id进行区分(就是动态子组件的key)

component diff

比较策略:

①  同一类型,按照原策略继续比较Virtual DOM;

②  如果不是同一类型,替换整个组件下所有的子节点;

③  通过shouldComponentUpdate来判断是否需要进行diff

element diff

同一层级时,提供插入、移动、删除3个操作

(具体的操作策略待补充)

patch

将tree diff比较计算出来的结果,更新到界面上的一个操作。


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值