View on GitHub

personal-study-nodes

个人学习过程中整理的一些笔记

React笔记

特点:

  1. 声明式编码(Declarative)
  2. 组件化编码(Component-Based)
  3. 支持客户端与服务器渲染(Learn Once,Write Anywhere)
  4. 高效
    • 虚拟(virtual)DOM,不总是直接操作DOM
    • DOM Diff 算法,最小化页面重绘
  5. 单向数据流

一、JSX简介

const element = <h1>Hello, world!</h1>;

JSX是一种标签语法,它既不是字符串也不是HTML。JSX也是一个表达式,在编译之后,JSX 表达式会被转为普通 JavaScript 函数调用,并且对其取值后得到 JavaScript 对象。

  1. JSX特定属性

    你可以通过使用引号,来将属性值指定为字符串字面量:

    const element = <div tabIndex="0"></div>;
    const element2 = <img src="images/01.jpg" />;		//可以直接使用 /> 闭合标签
    

    也可以使用大括号,来在属性值中插入一个 JavaScript 表达式:

    const element = <img src={user.avatarUrl}></img>;	//直接使用大括号可以防止注入攻击
    
  2. JSX 表示对象

    Babel 会把 JSX 转译成一个名为 React.createElement() 函数调用

    const element1 = (
      <h1 className="greeting">
        Hello, world!
      </h1>
    );
    const element2 = React.createElement(
      'h1',
      {className: 'greeting'},
      'Hello, world!'
    );
    //element1 和 element2 代码完全等效
    

二、元素渲染

语法:

ReactDOM.render(element, container[, callback])
  1. 会控制你传入容器节点里的内容。当首次调用时,容器节点里的所有 DOM 元素都会被替换,后续的调用则会使用 React 的 DOM 差分算法(DOM diffing algorithm)进行高效的更新。
  2. 不会修改容器节点(只会修改容器的子节点)。可以在不覆盖现有子节点的情况下,将组件插入已有的 DOM 节点中。

例子:写一个hello world

//html
<div id="root"></div>
//js
const element = <h1>Hello, world</h1>;
ReactDOM.render(element, document.getElementById('root'));

三、面向组件编程

1. 自定义组件

html:

<div id="example1"></div>
<div id="example2"></div>

js:

//方式1:工厂函数组件(简单组件)
function MyComponent(){
    return <h2>工厂函数组件简单组件</h2>
}
ReactDOM.render(<MyComponent />,document.getElementById('example1'))
//方式2:ES6类组件(复杂组件)
class MyComponent2 extends React.Component{
    render(){
        return <h2>ES6类组件复杂组件</h2>
    }
}
ReactDOM.render(<MyComponent2 />,document.getElementById('example2'))

2. 组件的三大属性

1> State

state(状态) 是组件对象的重要属性,值是对象(可以包含多个数据)

组件被称为“状态机”,通过更新组件的 state 来更新对应页面的显示(重新渲染组件)

例子:

//1. 创建组件类
class Like extends React.Component {
    //构造函数中初始化state
    constructor(props) {
        super(props);
        this.state = {
            isLikeEat: false
        }
        //将新增的方法,强制绑定为组件对象
        this.handleClick = this.handleClick.bind(this)
    }

    render() {
        //读取状态
        const {isLikeEat} = this.state
        return <h2 onClick={this.handleClick}>{isLikeEat ? '我喜欢吃' : '我讨厌吃'}</h2>
    }

    handleClick() {
        const isLikeEat = !this.state.isLikeEat
        //更新状态
        this.setState({isLikeEat})
    }
}

//2. 渲染组件
ReactDOM.render(<Like/>, document.getElementById('like_'))

2> Props

Props(属性)

例子:

    //1. 创建组件
    function Person(props) {
        return (
            <ul>
                <li>名称{props.name}</li>
                <li>年龄{props.age}</li>
                <li>性别{props.gender}</li>
            </ul>
        )
    }

    //指定属性默认值
    Person.defaultProps = {
        age: 18,
        gender: ''
    }

    //对属性进行类型限制和必要性限制
    Person.propTypes = {
        name: PropTypes.string.isRequired,
        age: PropTypes.number.isRequired
    }

    const p1 = {name: '没救', age: 12, gender: ''}

    //2. 渲染组件
    ReactDOM.render(<Person {...p1}/>, document.getElementById('person_1'))
    ReactDOM.render(<Person name="花花"/>, document.getElementById('person_2'))

3> Ref

例子:

    //1. 创建组件类
    class MyComponent extends React.Component {
        constructor(props) {
            super(props);
            this.blueInput = this.blueInput.bind(this)
            this.showInput = this.showInput.bind(this)
        }

        render() {
            return (
                <div>
                    <input type="text" ref="content"/>&nbsp;&nbsp;
                    <button onClick={this.showInput}>点击提示输入内容</button>
                    <input type="text" ref={input => this.input_ = input}
                           onBlur={this.blueInput} placeholder="失去焦点提示内容"/>
                </div>
            );
        }

        showInput() {
            //官方不推荐此写法
            const input = this.refs.content
            alert(input.value)
        }

        blueInput() {
            alert(this.input_.value)
        }
    }

    //2. 渲染组件
    ReactDOM.render(<MyComponent/>, document.getElementById('box'))

4> 整合复杂控件

    //1. 创建组件类
    //父组件,最上层的组件
    class App extends React.Component {
        constructor() {
            super();
            this.state = {
                todoList: ['吃饭', '睡觉', '玩游戏']
            }
            this.addTodo = this.addTodo.bind(this)
        }

        render() {
            const {todoList} = this.state
            return (
                <div>
                    <h1>Simple TODO List</h1>
                    <AddComponent next={todoList.length + 1} addTodo={this.addTodo}/>
                    <TodoList list={todoList}/>
                </div>
            );
        }

        addTodo(todo) {
            const {todoList} = this.state
            todoList.unshift(todo)
            this.setState({todoList})
        }
    }

    //增加控件,用来增加todo list
    class AddComponent extends React.Component {
        constructor() {
            super();
            this.handlerAddClick = this.handlerAddClick.bind(this)
            this.handlerKeyDown = this.handlerKeyDown.bind(this)
        }

        render() {
            return (
                <div>
                    <input type="text" onKeyDown={this.handlerKeyDown} 
        				ref={input => this.input = input}/>
                    <button onClick={this.handlerAddClick}>Add #{this.props.next}</button>
                </div>
            );
        }

        handlerAddClick() {
            let text = this.input.value.trim()
            if (text) {
                this.props.addTodo(text)
                this.input.value = ''
            }
        }

        handlerKeyDown(e) {
            //回车进入
            if (e.keyCode === 13) {
                this.handlerAddClick()
            }
        }
    }
    AddComponent.propTypes = {
        next: PropTypes.number.isRequired,
        addTodo: PropTypes.func.isRequired
    }

    //todo list 控件,显示待办内容
    class TodoList extends React.Component {
        render() {
            return (
                <div>
                    <ul>
                        {
                        this.props.list.map((item, index) => <li key={index}>{item}</li>)
                        }
                    </ul>
                </div>
            );
        }
    }
    TodoList.propTypes = {
        list: PropTypes.array.isRequired
    }

    //2. 渲染组件
    ReactDOM.render(<App/>, document.getElementById('box'))

3. 收集表单数据

4. 生命周期

声明式编程:类似jquery,不需要关注功能具体实现的过程,调用就行

参考资料 参考资料2 参考资料3

  1. 初始化阶段
static defaultProps = {
    name: 'sls',
    age:23
};
//or
Counter.defaltProps={name:'sls'}
constructor() {
    super();
    this.state = {number: 0}
}
  1. 运行中阶段
//该钩子函数可以接收到两个参数,新的属性和状态,返回true/false来控制组件是否需要更新。
shouldComponentUpdate(newProps, newState) {
    if (newProps.number < 5) return true;
    return false
}
  1. 销毁阶段

5. 虚拟DOM 和DOM Diff算法