react

 

 

Table of Contents

1 学习的基础

  • js/html/css 基础
  • webpack 基础
  • node 基础

2 使用环境

  • webstorm 最新的
  • windows10 最新的
  • node 最新的

3 创建项目

 

3.1 下载可用于创建项目包 create-react-app

yarn add create-react-app

3.2 创建项目

当前使用的版本(3.2.0)

npx create-react-app my-react

3.3 启动项目(根据package中的命令操作)

cd my-react
yarn start

4 react 知识点

知识点测试时都是修改 App.js 文件中的内容

import React from 'react';

function App() {
    return (
        ...修改的入口参考位置
    )
}
export default App;

使用 jsx 语法,jsx: javascript xml,变成js需要编译转换

4.1 只能挂一个标签

 

4.1.1 只能一个

<h1>hello world</h1>

4.1.2 两个会报错

<p>hello</p>
<p>world</p>

4.2 单标签必须自闭合(xml很严格)

<label>
  <span>name:</span>
  <input/>
</label>

4.3 使用变量

 

4.3.1 字符串直接用

<input type="text"/>

4.3.2 使用字面量

<input type={'text'}/>

4.3.3 使用变量

const msg = 'hello world';
......
<h1>{msg}</h1>

4.4 注释(需要使用变量形式)

<div>
  <span>1</span>
  {/*<span>111</span>*/}
</div>

4.5 关键字冲突

jsx 中属性关键字和js中关键字冲突(class、for),使用其他的词代替

<div>
  <label htmlFor={'hd'}>name:</label>
  <input className={'name'} id={'hd'}/>
</div>

4.6 表达式

 

4.6.1 字面量

<p>{123}</p>

4.6.2 求值表达式

<div>
  <p>1 + 1 = {1 + 1}</p>
  <p>1 > 2 is {(1 > 2).toString()}</p>
  <p>(5&gt;2)&amp;&amp;(5&lt;8) is {((5 > 2) && (5 < 8)).toString()}</p>
</div>

4.7 样式style

以对象形式来使用,属性的写法使用小驼峰(去掉连接符号)

<div style={{backgroundColor:'#f00'}}>11</div>

4.8 循环

key保持不变

['张三', '李四', '王五', '马六']
    .map((it, ix) => ({name: it, id: ix}))
    .filter(it=>it.id > 0)
    .map(it=>(
        <div key={it.id}>{it.name}</div>
    ))

4.9 条件渲染

<div>
  {2 >1 && <h1>hello world</h1>}
  {2 < 1 && <h1>hello world</h1>}
  {2 < 1 ? <h1>world</h1> : <h1>hello</h1>}
</div>

4.10 组件

 

4.10.1 创建组件

 
  1. 必须名称首字母大写
  2. render 必须存在
    //getter/setter 函数为了直接使用 this.xxx
    class Person extends React.Component {
        constructor(props) {
            super(props);
            this._name = 'master';
            this._age = 100;
        }
    
        get name() {
            return this._name;
        }
    
        set name(new_name) {
            this._name = new_name;
        }
    
        get age() {
            return this._age;
        }
    
        set age(new_age) {
            this._age = new_age;
        }
    
        render() {
            return (
              <div>
                  <h2>name: {this.name}</h2>
                  <h2>age: {this.age}</h2>
              </div>
            );
        }
    }
    

4.10.2 使用组件

直接当成一个标签使用

<Person/>

4.10.3 组件嵌套

直接使用Teacher组件,Teacher组件中使用了Student组件

class Student extends React.Component {
    render() {
        return (
            <span>学生</span>
        );
    }
}

class Teacher extends React.Component {
    render() {
        return (
            <div>
                <h1>teacher</h1>
                {
                    [1, 2, 3, 4, 5]
                        .map(it=>({name:it, id:'s' + it}))
                        .map(it=>(
                            <div key={it.id}>
                                <Student/>
                                {it.name}
                            </div>
                        ))
                }
            </div>
        );
    }
}

4.10.4 组件传值

 
  1. 简单使用
    class Person extends React.Component {
        constructor(props) {
            super(props);
        }
    
        render() {
            return (
                <div>
                    <h1>name: {this.props.name}</h1>
                    <h1>age: {this.props.age}</h1>
                </div>
            );
        }
    }
    
    ......
    
    <Person name={'Mrs Li'} age={25}/>
    
  2. 嵌套传参
    //组件
    class Item extends React.Component {
        constructor(props) {
            super(props);
        }
    
        render() {
            return (
                <p>{this.props.desc}: {this.props.text}</p>
            );
        }
    }
    
    class StudentList extends React.Component {
        constructor(props) {
            super(props);
        }
    
        render() {
            return (
                this.props.list.map(item => (
                    <ul key={item.id}>
                        <li>class: {item.class}</li>
                        <li>
                            <ul>
                                <li>
                                    <span>members: </span>
                                    {
                                        item.members.map(it => (
                                            <span key={it.id}> {it.name} </span>
                                        ))
                                    }
                                </li>
                            </ul>
                        </li>
                    </ul>
                ))
            );
        }
    }
    
    class Teacher extends React.Component {
        constructor(props) {
            super(props);
        }
    
        render() {
            return (
                <div>
                    <Item text={this.props.name} desc={'name'}/>
                    <Item text={this.props.age} desc={'age'}/>
                    <Item text={this.props.job} desc={'job'}/>
                    <p>students-list</p>
                    <StudentList list={this.props.students}/>
                </div>
            )
        }
    }
    
    ......(数据)
    
    const data = {
        name: 'Mrs Li',
        age: 55,
        job: 'teacher',
        students: [
            {
                class: '031',
                members: ['zhou', 'fru', 'mike']
            },
            {
                class: '037',
                members: ['张三', '李四', '王五']
            },
            {
                class: '007',
                members: ['Bob', 'Alex']
            }
        ]
    };
    data.students.forEach((item, index) => {
        item.id = 's' + index;
        item.members = item.members.map((it, ix) => (
            {id: 't' + ix, name: it}
        ));
    });
    
    ......(使用)
    
    <Teacher name={data.name}
             age={data.age}
             job={data.job}
             students={data.students}/>
    

4.11 事件

 

4.11.1 this 丢失

4.11.2 事件名称使用小驼峰

class Event extends React.Component {
    click() {
        console.log('clicking', window.Date.now());
    }

    render() {
        return (
            <h1 style={{textAlign: 'center'}}
                onClick={this.click.bind(this)}>点击</h1>
        );
    }
}

......

<Event/>

4.12 手动触发渲染更新

 

4.12.1 强制更新

很可能会影响效率,不推荐使用

class Count extends React.Component {
    constructor() {
        super();
        this.val = 0;
    }

    click() {
        ++this.val;
        console.log('click', this.val);
        this.forceUpdate();
    }

    render() {
        return (
            <div style={{textAlign: 'center'}}>
                <p>
                    <span>click times: {this.val}</span>
                </p>
                <p>
                    <input onClick={this.click.bind(this)}
                           type='button'
                           value='点击'/>
                </p>
            </div>
        );
    }
}

......

<Count/>

4.12.2 state 的方式

class Count extends React.Component {
    constructor() {
        super();
        this.state = {
            val: 0
        };
    }

    click() {
        this.setState({
            val: this.val + 1
        });
    }

    get val() {
        return this.state.val;
    }

    render() {
        console.log('rendering', window.Date.now());
        return (
            <div style={{textAlign: 'center'}}>
                <p>
                    <span>click times: {this.val}</span>
                </p>
                <p>
                    <input onClick={this.click.bind(this)}
                           type='button'
                           value='点击'/>
                </p>
            </div>
        );
    }
}

......

<Count/>

4.12.3 父组件传递给子组件的参数会同步更新

子组件不能修改父组件参数,参数是复杂对象则可以改其属性

class Child extends React.Component {
    constructor(props) {
        super(props);
    }

    render() {
        return (
            <p>
                子组件: {this.props.value}
            </p>
        );
    }
}

class Parent extends React.Component {
    constructor() {
        super();
        this.state = {
            value: 0
        };
    }

    get value() {
        return this.state.value;
    }

    click() {
        this.setState({
            value: this.value + 1
        });
    }

    render() {
        return (
            <div>
                <p>
                    父组件: {this.value}
                </p>
                <Child value={this.value}/>
                <p>
                    <input onClick={this.click.bind(this)}
                           value={'点击'}
                           type={'button'}/>
                </p>
            </div>
        );
    }
}

......

<Parent/>

4.13 children

 

4.13.1 使用儿子的形式,最里面的一层是标签的内容,是个字符串

4.13.2 组件也是类似的,就是替换了一个标签

4.13.3 儿子没有则为空,多个则是一个数组(树节点)

4.13.4 元素中的属性生成对应的参数

const a =
    <h1>
        <p style={{background: '#f86'}}>
            <span>color</span>
        </p>
    </h1>;
const b = a.props.children;
const c = b.props.children;
const d = b.props.style;

......

{c}
{b}
{a}
<p>background: {d.background}</p>

4.14 子组件根据父组件参数发请求获取参数

 

4.14.1 很容易出现 update 循环,update 之后获取数据继续 update

处理方法:在 shouldComponentUpdate 中控制更新

class Child extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            time: -1
        };
        this.request();
    }

    shouldComponentUpdate(nextProps, nextState, nextContext) {
        console.log(nextProps, nextState)
        return nextProps.val !== this.props.val ||
            this.state.time !== nextState.time;
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        this.request();
    }

    request() {
        setTimeout(() => {
            this.setState({
                time: this.props.val
            });
        }, 500);
    }

    render() {
        console.log('rendering');
        return (
            <div>
                <p>click times: {this.props.val}</p>
                <p>time: {this.state.time}</p>
            </div>
        );
    }
}

class Parent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            val: 0
        };
        console.log('constructor')
    }

    componentDidCatch(error, errorInfo) {
        console.log('catch')
    }

    componentDidMount() {
        console.log('mount');
    }

    componentDidUpdate(prevProps, prevState, snapshot) {
        console.log('update');
    }

    componentWillUnmount() {
        console.log('unmount');
    }

    shouldComponentUpdate(nextProps, nextState, nextContext) {
        console.log('should update');
        // console.log(nextProps, nextState, nextContext)
        return true;
    }

    click() {
        this.setState({
            val: this.state.val + 1
        });
    }

    render() {
        console.log('render');
        return (
            <div>
                <Child val={this.state.val}/>
                <p>
                    <input type={'button'}
                           onClick={this.click.bind(this)}
                           value={'click'}/>
                </p>
            </div>

        );
    }
}

4.14.2 在父组件中获取数据传入子组件则没有 update 循环(看情况选择)

4.15 子组件向父组件传参

使用调用函数的方式传递参数

class Child extends React.Component {
    constructor(props) {
        super(props);
        this.cnt = 0;
    }

    clickHandler() {
        this.props.message('msg--' + ++this.cnt);
    }

    render() {
        return (
            <div>
                <input value={'click'}
                       onClick={this.clickHandler.bind(this)}
                       type={'button'}/>
            </div>
        );
    }
}

class Parent extends React.Component {
    constructor() {
        super();
        this.state = {
            msg: 'waiting click'
        }
    }

    message(msg) {
        this.setState({
            msg
        });
    }

    render() {
        return (
            <div>
                <p>message: {this.state.msg}</p>
                <Child message={this.message.bind(this)}/>
            </div>
        );
    }
}

......

<Parent/>

4.16 引用(可操作组件)

ref 值重复会覆盖,最有一个有效

4.16.1 简单引用

组件也同样适用

class Reference extends React.Component {
    componentDidMount() {
        console.log(this.refs.test.id);
    }

    render() {
        return (
            <div>
                <input ref={'test'} id={123}/>
            </div>
        );
    }
}

......

<Reference/>

4.16.2 父组件使用子组件的数据

class Child extends React.Component {
    constructor(props) {
        super(props);
        this.val = 'child' + this.props.id;
    }
    render() {
        return (
            <div>
                <p>{this.val}</p>
            </div>
        );
    }
}

class Parent extends React.Component {
    componentDidMount() {
        console.log(this.refs.first_child.val);
        console.log(this.refs.second_child.props.id);
    }

    render() {
        return (
            <div>
                <Child ref='first_child' id={1}/>
                <Child ref='second_child' id={2}/>
            </div>
        );
    }
}

......

<Parent/>

4.16.3 子组件使用父组件的数据

就是个普通的参数传递

class Child extends React.Component {
    render() {
        return (
            <div>
                <p>{this.props.parent.val}</p>
            </div>
        );
    }
}

class Parent extends React.Component {
    constructor() {
        super();
        this.val = 'parent';
    }
    render() {
        return (
            <div>
                <Child parent={this}/>
            </div>
        );
    }
}

......


<Parent/>

4.17 受控表单元素

 

4.17.1 input,select 作为输入,绑定了 value

4.17.2 原始用法使用 defalutValue 来替代 value

4.17.3 受控的表单元素需要绑定 change 事件

class Form extends React.Component {
    constructor() {
        super();
        this.state = {
            val: ''
        };
    }

    handlerChange(event) {
        this.setState({
            val : event.target.value
        });
    }

    render() {
        return (
            <div>
                <p>
                    <input type={'text'}
                           onChange={this.handlerChange.bind(this)}
                           value={this.state.val}
                           placeholder={'请输入名称'}/>
                </p>
                <p>
                    <input defaultValue={'默认值'}/>
                </p>
                <p>
                    <input type={'password'}
                           placeholder={'请输入密码'}/>
                </p>
            </div>
        );
    }
}

......

<Form/>

Created: 2019-11-29 周五 23:11

Validate

posted @ 2019-11-29 23:14  heidekeyi  阅读(137)  评论(0编辑  收藏  举报