react之旅(四)react 如何调用方法;获取数据;改变数据;方法传值

本文主要讲解react组件中如何定义方法,调用方法,获取数据,改变数据,方法传值,调用方法时改变this指向。

一、react中调用方法

import React from 'react';

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

    runFun() {
        console.log("runfun");
    }

    render(){
        return(
            <div>
                <button onClick={this.runFun()}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

这个地方的意图是点击按钮打印’runfun’,看下实际效果:
react之旅(四)react 如何调用方法;获取数据;改变数据;方法传值_第1张图片
可以看到,没有点击,但是方法runFun已经调用了,这个地方的原因是runFun方法后面加了括号,加上括号之后就表示要调用这个方法,所以更改如下:

import React from 'react';

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

    runFun() {
        console.log("runfun");
    }

    render(){
        return(
            <div>
                <button onClick={this.runFun}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

去掉runFun后面的括号后得到了预期的结果:每点击一次按钮执行一次runFun方法。

二、react中获取数据

现在想要点击按钮获取state中的值,这个改如何实现?

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值"
        }
    }

    runFun() {
        console.log(this.state.msg);
    }

    render(){
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <br />
                <button onClick={this.runFun}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

react之旅(四)react 如何调用方法;获取数据;改变数据;方法传值_第2张图片
看到报了一个这样的错误,TypeError: Cannot read property 'state' of undefined,报这个错误的原因是this指向的问题,this指向可以参考:js之旅(七)js中this
在react中,可以用三种方式改变this指向

2.1 调用时bind函数改变this指向

可以在调用函数的时候借助于bind函数来改变被调用方法中的this指向。

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值"
        }
    }

    runFun() {
        console.log(this.state.msg);
    }

    render(){
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <br />
                <button onClick={this.runFun.bind(this)}>runFun</button>
            </div>
        )
    }
}

2.2 在构造函数中改变方法的this执行

可以在构造函数中,一开始就改变this的指向。

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值"
        }
        this.runFun = this.runFun.bind(this);
    }

    runFun() {
        console.log(this.state.msg);
    }

    render(){
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <br />
                <button onClick={this.runFun}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

这样也可以得到想要的效果。

2.3 使用箭头函数

可以将被调用的函数定义成箭头函数,这样就不用关心this指向的问题。

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值"
        }
    }

    runFun = () => {
        console.log(this.state.msg);
    }

    render(){
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <br />
                <button onClick={this.runFun}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

三、改变数据

3.1 如何改变state中的值

将数据放到state中,怎样去改变state中的值呢?在react中,可以调用setState方法来改变state的值当state值被改变后,会重新执行render方法,渲染数据。

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            test: "test",
            msg: "state中的值"
        }
    }

    changeData = () => {
        this.setState({
            msg: "改变后state中的值"
        })
    }

    render(){
        return(
            <div>
                <div>{this.state.test}</div>
                <br />
                <br />
                <div>{this.state.msg}</div>
                <br />
                <br />
                <button onClick={this.changeData}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

可以看到,调用setState方法后,重新执行render方法重新渲染页面,而且,setState方法仅仅改变被修改的值,对state对象中的其它值没有影响

3.2 改变state的值后render函数的调用情况

下面有个疑问?多次改变state中的值,render方法调用几次?

	//情景一
	this.setState({
            msg: {
                msg: "改变后state中的值",
                test: "改变后state中的值1"
            }
        });
     //情景二
	this.setState({
            msg: "改变后state中的值",
            test: "改变后state中的值1"
        });
     //情景三
	this.setState({
           msg: "改变后state中的值",
        });
	this.setState({
           test: "改变后state中的值1"
        });

上面这三种情景都会调用两次render方法。是不是可以得出结论:改变几个值就会调用几次render方法?这是错误的!!!!,为什么这样说?先举一个反例:

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值",
            msg1: "msgs",
            msg2: "msg2",
            msg3: "msg3"
        }
    }

    runFun = () => {
        this.setState({
            msg: "改变后state中的值",
        });
        this.setState({
            msg1: "改变后msgs",
        });
        this.setState({
            msg2: "改变后msg2",
        });
        this.setState({
            msg3: "改变后msg3"
        });
        
    }

    render(){
        console.log("render");
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <div>{this.state.msg1}</div>
                <br />
                <div>{this.state.msg2}</div>
                <br />
                <div>{this.state.msg3}</div>
                <br />
                <button onClick={this.runFun}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

react之旅(四)react 如何调用方法;获取数据;改变数据;方法传值_第3张图片
发现改变了四个值,render方法任然是调用了2次。
看一下官方说明:
在这里插入图片描述
setState之后发生的事情

  • setState操作不会立即更新组件
  • React会将state的改变压入栈中,在合适的时机,批量更新state和视图
    所以说,setState并不是立即更新的,和调用几次基本上关系不大

3.2 setState后render为什么总是调用2次

因为 React 在 Dev mode(开发模式) 下会刻意执行两次渲染,以防止组件内有什么 side effect 引起 bug,提前预防。

3.3 直接改变state中的值行不行?

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值",
            msg1: "msgs",
            msg2: "msg2",
            msg3: "msg3"
        }
    }

    runFun = () => {
        this.setState({
            msg: "改变后state中的值",
        });
        this.setState({
            msg1: "改变后msgs",
        });
        this.setState({
            msg2: "改变后msg2",
        });
        
        this.state.msg3 = "test msg3"
        
    }

    render(){
        console.log("render");
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <div>{this.state.msg1}</div>
                <br />
                <div>{this.state.msg2}</div>
                <br />
                <div>{this.state.msg3}</div>
                <br />
                <button onClick={this.runFun}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

实际测过发现是可以的,为什么网上都说不行?看下面的代码:

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值",
            msg1: "msgs",
            msg2: "msg2",
            msg3: "msg3"
        }
    }

    runFun = () => {
        this.setState({
            msg: "改变后state中的值",
        });
        this.setState({
            msg1: "改变后msgs",
        });
        this.setState({
            msg2: "改变后msg2",
        });
        this.setState({
            msg3: "改变后msg3",
        });
        
        this.state.msg3 = "test msg3"
        
    }

    render(){
        console.log("render");
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <div>{this.state.msg1}</div>
                <br />
                <div>{this.state.msg2}</div>
                <br />
                <div>{this.state.msg3}</div>
                <br />
                <button onClick={this.runFun}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

发现msg3并没有使用直接赋值的值,而是用了setState中的值。
这个地方可以这样理解:

  • 直接修改state中字段的值是生效的,但是直接修改是不会触发render方法,故不会刷新页面,所以直接修改了state中的字段1,又用setState修改了字段2,就会在页面上看到字段1也被修改了
  • 如果即用setState修改了字段1,也直接修改了state中的字段1,它会以setState中的修改为准:直接修改state中的字段是立即生效的,但是setState方式修改它会将修改放入栈中,在合适的时机批量刷新state中的值,这个时候会覆盖掉直接修改后的值,表现形式就是以setState的修改为准。

四、方法传值

借助于bind方法,可以实现给方法传值:

import React from 'react';

class Demo1 extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            msg: "state中的值"
        }
    }

    changeData(msg){
        this.setState({
            msg: msg
        });
        
    }

    render(){
        console.log("render");
        return(
            <div>
                <div>{this.state.msg}</div>
                <br />
                <br />
                <button onClick={this.changeData.bind(this, "改变后msg的值")}>runFun</button>
            </div>
        )
    }
}

export default Demo1;

你可能感兴趣的:(react,react)