4

JSX 基本语法

1.定义标签时只允许被一个标签包裹
const component = <span>name</span><span>age</span>

2.标签一定要闭合
<span></span>

3.DOM元素属性class和for
class属性改为className   
<div className="myClass"></div>
for属性改为htmlFor 
<label htmlFor="myInput"></label> <input value="a" name="myInput"/>

4.自定义html属性,要使用data-前缀
<div data-attr="xxx"></div>

5.属性值需要使用表达式,只要用{}替换""即可
const person = <Person name={window.isLoggerdIn ? window.name : ''}>

6.html转义
React会将所有要显示到DOM的字符串转义,防止XSS
react提供了dangerouslySetInnerHTML属性,谨慎使用

React 数据流

在React中,数据是自顶向下单向流动的,即从父组件到子组件,这条原则让组件之间的关系变的简单且可预测。state和props是React组件中重要的概念,如果顶层组件初始化props,那么React会向下遍历整棵组件树,重新尝试渲染所有相关的子组件。而state只关心每个组件自己内部的状态,这些状态只能在组件内部改变,把组件看成一个函数,那么它接受了props作为参数,内部由state作为函数的内部参数,返回一个Virtual DOM的实现。

组件的state
组件的state是组件的内部状态,state的变化最终将反映到组建UI的变化,我们在组件的构造方法constructor中通过this.state定义组件的初始状态,并通过this.setState方法改变组件状态(也是改变组件状态的唯一方式),进而组件的UI也会随之重新渲染。

1.setState是一个异步方法,一个生命周期内所有的setState方法会合并操作。

组件的props

1.React的单向数据流,主要的流动管道就是props,
props本身是不可变的。当我们试图改变props的原始值时,
React会报出类型错误警告,组件的props一定来自于默认属性或者通过父组件传递而来。

2.React为props同样提供了默认的配置。
通过defaultProps静态变量的方式来定义,当组件被调用的时候,默认值保证渲染后始终有值。
    static defaultProps = {
        classPrefix: 'tabs',
        onChange: () => {}    
    }
    
3.proTotypes用于规范props的类型与必需的状态。
如果组件定义了propTypes,那么在开发环境下,就会对组件的props的值类型作检查。
    static propTypes = {
        classPrefix: propTypes.String
    }
    
4.子组件的props,在React中有一个重要且内置的props---children,
它代表组件的子组件集合,children可以根据传入子组件的数量来决定是否是数组类型。

5.用function prop与父组件通讯,
父组件可以通过子组件的prop传递给子组件一个回调函数,
子组件需要改变父组件数据时,调用这个回调函数即可。

React生命周期

组件从创建到被销毁的过程称为组件的生命周期。通常,React组件的生命周期可以被分为三个阶段:挂载阶段、更新阶段、卸载阶段

1.挂载阶段

constructor
这是es6 class的构造方法,组件被创建时,
会首先调用组件的构造方法,
这个构造方法接收一个props参数,props是父组件中传入的属性对象

componentWillMount
该方法在组件被挂载到DOM前调用,且只会被调用一次

render
这是定义组件时唯一必要的方法,该方法根据props和state返回一个react元素
,这个元素用于描述组件的UI,注意render并不负责组件的实际渲染工作,
它只是返回一个UI的描述,真正渲染出页面的DOM的工作有React负责。

componentDidMount 
组件被挂载到DOM后调用,且只会被调用一次

2.更新阶段

componentWillReceiveProps(nextProps)
这个方法只在props引起的组件更新过程中,才会被调用。
state引起的组件更新并不会触发该方法的执。

shouldComponentUpdate(nextProps, nextState)
这个方法决定组件是否继续执行更新过程,当方法返回true时(默认返回值),
组件会继续更新过程。返回false时,组件更新过程停止。

componentWillUpdate(nextProps, nextState)
该方法在组件render调用前调用。

render
该方法根据props和state返回一个react元素,如挂载阶段

componentDidUpdate(preProps, preState)
组件更新后被调用,可以作为操作DOM的地方。两个参数分别是组件更新前的props和state

3.卸载阶段

componentWillUnmount
组件被卸载之前调用,此处可以用于清除定时器等,取消监听事件等,避免引起内存泄露。

React refs

ref是react上的特殊属性
在常规的数据流之外强制修改子元素
被修改的可以是react组件实例,或者一个dom元素
可以在dom元素上和类组件上添加ref,react组件在加载时将dom元素传入ref的回调,在componentDidMount 或者componentDidUpdate 这些生命周期前执行。

1.dom元素上添加ref

...
handleClick(){
    this.nameInput.focus();
}

render(){
    return(
        <div>
            <input ref={(input)=>{this.nameInput = input;}}
            <button onClick={this.handleClick}>点击获取输入框焦点</button>
        </div>
    );
}

2.react组件上添加ref

// App.js
otherFunction(){
    this.pager.changePage(5);
}
....
render(){
    return(
        <Pager ref={(page)=>{this.pager = page;}} />
    );
}

// Pager.js
...
changePage(page){
    this.setState({
        page : page
    });
}
...
// 在父组件中使用ref给某一子组件传值,并且子组件调用setState修改自身的状态,
// 该子组件会重新渲染一次,父组件中的其他组件不会重新render

3.ref和函数式组件

function MyTest(){
    let textInput = null;

    function handleClick(){
        textInput.focus();
    }

    return(){
        <div>
            <input ref={(input)=>{textInput=input}/>
            <button onClick={handleClick}>点击获取输入框焦点</button>
        </div>
    }
}
  1. 子组件对父组件暴露dom节点
    // App.js
    ...
    render(){

    return(
        <Sub inputRef={ el => this.inputRef = el; } />
    );

    }

    // Sub.js
    ...
    render(){

    return(){
        <div>
            <input ref={this.props.inputRef} />
        </div>
    }

    }

React forceUpdate

默认情况下,当组件的 state 或 props 改变时,组件将重新渲染。 如果你的 render() 方法依赖于一些其他数据,你可以告诉 React 组件需要通过调用 forceUpdate() 重新渲染。
调用 forceUpdate() 会导致组件跳过 shouldComponentUpdate() ,直接调用 render()。 这将触发子组件的正常生命周期方法,包括每个子组件的 shouldComponentUpdate() 方法。
forceUpdate就是重新render。有些变量不在state上,但是你又想达到这个变量更新的时候,刷新render;或者state里的某个变量层次太深,更新的时候没有自动触发render。这些时候都可以手动调用forceUpdate自动触发render

// Sub.js
class Sub extends React.Component{
    construcotr(){
        super();
        this.name = "tom";
    }
    refChangeName(name){
        this.name = name;
        this.forceUpdate(); 
    }
    render(){
        return (<div>{this.name}</div>);
    }
}

// App.js
class App extends React.Component{

    handleClick(){
        this.subRef.refChangeName("jack");
    }
    render(){
        return (<div>
            <Sub ref={(sub)=>{this.subRef = sub;}} />
            <button onClick={this.handleClick}>click</button>
        </div>);
    }
}

zer0_li
1.4k 声望307 粉丝

经不住似水流年,逃不过此间少年