React常用知识总结

1、状态更新status

(1)status的初始化

status的初始化需要在构造方法里面,使用=赋值一个对象进行初始化数据。

import React from "react";

class App1 extends React.Component {

    constructor(props) {
        super(props);
        this.state = {
            age: 15
        }
    }

}

export default App1

(2)status的更新状态

status更新数据使用setStatus方法,可以传递一个对象和一个函数。

  • 可以接收一个函数,这个函数接受两个参数,第一个参数表示上一个状态值,第二参数表示当前的 props;
this.setState({
  age: 2,
});
  • 也可以接受一个对象
/**
 * 
 * 接收一个参数,该参数表示设置数据之前的参数,变更之前的参数
 */
this.setState(prevState => ({ 
      age:20 
}));

/**
 * 接收两个参数,prevState表示变化前的数据,props表示变化后的数据
 */
this.setState((prevState, props) => {
  return {
    age: prevState.age + 1
  };
});

this.setState((prevState, props) => ({
    age: prevState.age + 1
}));

2、生命周期

  • 直接加载:constructor -> componentWillMount -> componentDidMount
  • 更新status:componentWillUpdate -> shouldComponentUpdate

componentWillMount:组件即将被挂载(渲染到页面)的时候执行,只执行一次

componentDidMount:组件被挂载之后(页面渲染完成)的时候执行,只执行一次

shouldComponentUpdate返回值:组件是不是要被更新?

  • false:不要更新
  • true:要更新,一般是true

componentWillUpdate:当组件将更新时候执行,shouldComponentUpdate返回true时候被执行,false这不会被执行

componentDidUpdate:组件更新完毕之后执行

componentWillReceiveProps:前提:从父组件接收参数。当父组件的render函数被执行了,子组件的这个生命周期函数会被执行。当前组件没有prop传值的时候不会被执行

import React from "react";

/**
 * 生命周期
 */
class App2 extends React.Component {
    constructor(props) {
        console.log('constructor')
        super(props);
        this.state = {
            num: 1
        }
    }

    /**
     * 此处发起请求会引起主线程阻塞
     */
    componentWillMount() {
        console.log('componentWillMount')
    }

    /**
     * 网上流传此处发起请求会引起二次render
     *
     * 官方推进实际从这个地方进行忘了请求
     */
    componentDidMount() {
        console.log('componentDidMount')
    }

    /**
     * 将要更新
     * @param nextProps
     * @param nextState
     * @param nextContext
     */
    componentWillUpdate(nextProps, nextState, nextContext) {
    }

    /**
     * 更改数据后会触发
     *
     * false:更新后不会回调其他函数
     * true:更新后会回调其他函数
     */
    shouldComponentUpdate(nextProps, nextState, nextContext) {
        console.log('shouldComponentUpdate')
        return false;
    }

    changeHandler(e) {
        this.setState({
            num: e.target.value
        })
    }

    /**
     * 渲染的过滤
     * @returns {*}
     */
    render() {
        console.log('render')
        return (
            <div>
                我是是数字:{this.state.num}
                <hr/>
                <input type={'text'} value={this.state.num} onChange={event => {
                    this.changeHandler(event)
                }}/>
            </div>
        );
    }
}

export default App2

3、传值props

  • 传递变量
  • 传递dom
  • 传递方法

(1)父——>子

import React from "react";

/**
 * proper传值
 * 1、传递变量
 * 2、传递dom
 *
 * this.props.children 可能存在3种情况:对象、数组、undefined
 */
class App3 extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <Son name={'张三'} age={'66'}>
                <ul>
                    <li>1</li>
                    <li>2</li>
                    <li>3</li>
                </ul>
            </Son>
        );
    }
}

class Son extends React.Component {
    constructor(props) {
        super(props);
    }
    render() {
        return (
            <div>
                <p>Name: {this.props.name}</p>
                <p>age: {this.props.age}</p>
                <p>child:{this.props.children}</p>
            </div>
        );
    }
}

export default App3

(2)子——>父

import React from "react";

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            aChildMag: ""
        }
        this.getChildMag = this.getChildMag.bind(this);
    }

    render() {
        return (
            <div>
                <A msg = {this.getChildMag} />
                <h3>A子组件传来的值为:{this.state.aChildMag}</h3>
            </div>
        );
    }

    getChildMag(mag) {
        this.setState({
            aChildMag: mag
        })
    }
}

class A extends React.Component {
    render() {
        return (
            <button onClick={()=>{this.props.msg('AAA-哈哈哈')}}>点击</button>
        );
    }
}

export default App;

(3)子——>子

import React from "react";

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            aChildMag: ""
        }
        this.getChildMag = this.getChildMag.bind(this);
    }

    render() {
        return (
            <div>
                <A msg = {this.getChildMag} />
                <h3>A子组件传来的值为:{this.state.aChildMag}</h3>
                <B msg = {this.state.aChildMag} />
            </div>
        );
    }

    getChildMag(mag) {
        this.setState({
            aChildMag: mag
        })
    }
}

class A extends React.Component {
    render() {
        return (
            <button onClick={()=>{this.props.msg('AAA-哈哈哈')}}>点击</button>
        );
    }
}

class B extends React.Component {
    render() {
        return (
            <h3>这行数据是子组件A传递过来的:{this.props.msg}</h3>
        );
    }
}

export default App;

4、属性的约定和传值

在子类中约定数据类型,父类传递数据的时候必须传递该数据类型,否则发出警告,详细如下:

import React from "react";
import PropTypes from "prop-types"

class TodoItem extends React.Component {

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

    render() {
        const {text, itemVlue} = this.props;
        return (
            <React.Fragment>
                <div onClick={event => this.handleItemDelete()}>
                    {text} - {itemVlue}
                </div>
            </React.Fragment>
        );
    }

    /**
     * 子组件如何修改父组件的内容?
     */
    handleItemDelete() {
        const {itemDelete, itemIndex} = this.props;
        itemDelete(itemIndex)
    }
}

/**
 * 强制类型校验
 * @type {{itemDelete: Requireable<(...args: any[]) => any>, itemIndex: Requireable<number>, content: Requireable<string>}}
 */
TodoItem.propTypes = {
    //content: PropTypes.string,
    content: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), //既可以是number又可以是String:
    itemDelete: PropTypes.func,
    itemIndex: PropTypes.number, // 更改:itemIndex: PropTypes.number为itemIndex: PropTypes.string类型不一致,会抛出警告1
    text: PropTypes.string.isRequired //text没有传递,不报错,应为发现没有传递并不会去检测,如果加上isRequired,则有警告2,这时候需要定义默认值
}

//1、Warning: Failed prop type: Invalid prop `itemIndex` of type `number` supplied to `TodoItem`, expected `string`
//2、Warning: Failed prop type: The prop `text` is marked as required in `TodoItem`, but its value is `undefined`.

/**
 * 默认属性:对于传递的值没有传递则设置默认值,设置默认值,同事如果有强制类型校验isRequired,则不会发出警告,例如Text
 */
TodoItem.defaultProps = {
    text: '我是默认数据'
}

export default TodoItem

为了防止多余的div嵌套出现多层:

  • 在React16以上版本使用return ([])代码return()
  • 兼容低版本则使用return <React.Fragment></React.Fragment>包裹

6、路由匹配

  •  <NavLink to={'/man'} activeStyle={{color: 'red'}}>男样式</NavLink>
  •  <Route path={'/'} exact component={Home}></Route>
  •  <Redirect to={'/'}/>
  1.  exact:表示精确匹配,首页/使用,因为/太多,会匹配太多东西 ;其他页面不需要使用
  2.  Switch:横向匹配,只匹配置一个。不设置的话像/man,/ma这样就会出现异常
  3.  Drdirect:用于都没有匹配上设置404,配合Switch放在最后一行。to显示默认地址
  4.  NavLink:页面跳转,Navlink是link标签的升级版本,内部被渲染成a标签
import React from "react";
import {
    BrowserRouter as Router,
    Switch,
    Route,
    Link,
    Redirect, NavLink
} from "react-router-dom";

/**
 *
 * 问了防止多余的div嵌套出现多层,
 * 1、在React16以上版本使用return ([])代码return()
 * 2、兼容低版本则使用return <React.Fragment></React.Fragment>包裹
 *
 * exact:表示精确匹配,首页/使用,因为/太多,会匹配太多东西 ;其他页面不需要使用
 * Switch:横向匹配,只匹配置一个。不设置的话像/man,/ma这样就会出现异常
 * Drdirect:用于都没有匹配上设置404,配合Switch放在最后一行。to显示默认地址
 *
 * @returns {*}
 */
class App5 extends React.Component {

    render() {
        return ([
            <div>
                <h3>头部</h3>
                <Router>
                    {/*Navlink是link标签的升级版本,内部被渲染成a标签*/}
                    <NavLink to={'/man'} activeStyle={{color: 'red'}}>男样式</NavLink>
                    <NavLink to={'/ma'} activeClassName='selected'>女样式</NavLink>

                    <Route path={'/'} exact component={Home}></Route>
                    <Route path={'/a'} component={Footer}></Route>

                    <Switch>
                        <Route path={'/ma'} component={Ma}></Route>
                        <Route path={'/man'} component={Man}></Route>
                    </Switch>

                    <Redirect to={'/'}/>
                </Router>
                <h3>底部</h3>
            </div>
        ])
    }
}

class Home extends React.Component {
    render() {
        return (
            <h1>
                我是首页
            </h1>
        );
    }
}

class Footer extends React.Component {
    render() {
        return (
            <h1>
                我是Footer
            </h1>
        );
    }
}

class Man extends React.Component {
    render() {
        return (
            <h1>
                我是Man
            </h1>
        );
    }
}

class Ma extends React.Component {
    render() {
        return (
            <h1>
                我是Ma
            </h1>
        );
    }
}

export default App5

7、路由传参

字符串的传递方式:

<Route path={'/article/:id'} component={Article}/>

访问:http://localhost:3000/article/6

console.log(this.props.match.params.id)

可以拿到id

import React from "react";
import {
    BrowserRouter as Router,
    Switch,
    Route,
    Link,
    Redirect, NavLink
} from "react-router-dom";

class App6 extends React.Component {
    render() {
        return (
            <div>
                <h1>头部</h1>
                <Router>
                    {/*字符串的传递方式*/}
                    <NavLink to={'/article/5'}>去article</NavLink>
                    <Route path={'/article/:id'} component={Article}/>
                </Router>/
                <h1>底部</h1>
            </div>
        );
    }
}

class Article extends React.Component {

    componentWillMount() {
        //这块能拿到数据
        console.log(this.props.match.params.id)
    }

    render() {
        return (
            <div>
                <h1>文章组件</h1>
            </div>
        );
    }
}

export default App6

8、子组件调用父组件的方法

    /** 
     * 父组件的handleItemDelete方法传递到子类
     **/
    getTodoList() {
        return (
            this.state.list.map((value, index) => {
                return <Item
                    key={index}
                    itemVlue={value}
                    itemIndex={index}
                    itemDelete={this.handleItemDelete.bind(this)}>
                    {/*这块需要强制绑定为父组件的this,否则在子组件中找不到*/}
                </Item>
            })
        );
    }

    handleItemDelete(index) {
        //注意,这里不能直接修改status的list,不符合规范
        const list = [...this.state.list]
        list.splice(index, 1)
        this.setState({
            list: list
        })
    }   
class Item extends React.Component {

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

    render() {
        return (
            <React.Fragment>
                <div onClick={event => this.handleItemDelete()}>
                    {this.props.itemVlue}
                </div>
            </React.Fragment>
        );
    }

    /**
     * 子组件如何修改父组件的内容?
     */
    handleItemDelete() {
        this.props.itemDelete(this.props.itemIndex)
    }
}

export default Item

9、React动画

import React, {Fragment, Component} from 'react';
import './style.css'

class App extends Component {

    constructor(prop) {
        super(prop);
        this.state = {
            isShow: true
        }
        this.handleToggle = this.handleToggle.bind(this)
    }

    render() {
        return (
            <Fragment>
                <div className={this.state.isShow ? 'show' : 'hide'}>React动画</div>
                <CSSTransition
                    in={this.state.isShow}
                    timeout={1000}
                    classNames="fade"
                    unmountOnExit
                    onEnter={(el) => el.style.color='blue'}
                    appear={true}
                >
                    <div>CSSTransition动画</div>
                </CSSTransition>
                <button onClick={event => this.handleToggle()}>toggle</button>
            </Fragment>
        );
    }

    handleToggle() {
        this.setState({
            isShow: this.state.isShow ? false : true
        })
    }
}

export default App;

style.css

.show {
    opacity: 1;
    transition: all 1s ease-in;
}

.hide {
    animation: hide-item 2s ease-in forwards;
}

第三方框架:react-transition-group

React Transition Group

10、this指向问题

  • 普通函数中this的指向,是this执行时的上下文
  • 箭头函数中this的指向,是this定义时的上下文

11、模块化使用

        index.css如果多个模块都有index.css,还存在index.css都有title这个className这种情况css就冲突了,因为最终都会放在App.js中执行,例如hellow/index.css和title/index.css都有:

.title {
    background: red;
}

        有两种方式:

(1)使用less-->使用场景多

 .hello {
    .title {
        background: #61dafb;
    }
 }

(2)在index.css中间加上模块名称,例如index.module.css,这里的module不能改成其他的--->使用场景不太多

 hellow/index.js使用如下:

 import hello from './index.module.css'

 export default function Hello(){
    return <div className={hello.title}>hello</div>
 }

12、快捷键使用-westrom

  • rcc:创建一个类组件
  • rsf:创建一个函数组件

在settings -> Editor -> Live Templates可以修改或者添加模板样式。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值