React 组件

React的组件可以分为函数组件类组件。函数组件样式简单,但是不能拥有自己的内部状态。相反的,类组件写起来比较复杂,但是功能却比较强大。

函数组件

直接上代码:

function App() {
    function add([x, y]) {
        return x + y
    }
    return (
        <div>
            <Box name='leo' add1={add}></Box>
        </div>
    )
}

function Box(props) {//
    return (
        <div>
            {props.name}
            {props.add1([1, 5])}

        </div>
    )
}

上面代码就是两个简单的父子函数组件,子组件要获取父组件的内容,可以通过传参的方法,props就是参数。

类组件

先把上面的两个父子组件改为class的型式:

  class App extends React.Component {
    add([x, y]) {
        return x + y
    }

    render() {
        return (
            <div>
                <Box name='leo' add1={this.add.bind(this)}></Box>
            </div>
        )
    }
}

class Box extends React.Component {
    render() {
        console.log(this)
        console.log(this.props)
        return (
            <div>
                {this.props.name}
                {this.props.add1([1, 5])}
            </div>

        )
    }
}

这段代码难以理解的有:

  1. 每个组件中的this是什么
  2. 子组件中:this.props是什么
  3. 父组件的中:add1={this.add.bind(this) 为什么要.bind(this)

解答

  1. 在class中,this是指组件本身
  2. this.props 是一个对象,里面存储着this的属性。
    比如在子组件Box中,this.props就是存储Box的属性的对象,打出来就是
    Box{props :name : 'leo' ,add1: f() }
  3. 这一个问题比较复杂,简单的说,就是绑定add()这个函数的this为原组件,在上面那个例子中就是App。需要用另一例子才能解释:
    我们还是写两个类组件,父组件是App,子组件是Box。子组件的props对象里面有两个属性,一个属性名为add1,属性值为App.add,是一个函数;一个属性名为age,属性值为App.state.age。子组件的constructor()会调用父组件App的add()函数,让App.state.age的值改变。正确的代码为:
//父组件
class App extends React.Component {
    constructor() {
        super()
        this.state = {
            age: 0
        }
    }
    add() {
        setTimeout(() => {
            this.setState({
                age: 2
            })
        }, 2000)
    }
    render() {
        return (
            <div>
                <Box add1={this.add.bind(this)} age={this.state.age} ></Box>
            </div>
        )
    }
}

//子组件
class Box extends React.Component {
    constructor(props) {
        super()
        let n = 1
        if (n === 1) {
            props.add1()
            n += 1
        }
    }
    render() {
        return (
            <div>
                {this.props.age}
            </div>
        )
    }
}

现在可以开始解释为什么要绑定this了:

  1. 子组件的props.add1()这个代码,会找到props也就是存储Box的属性的对象的地址,然后在里面找到add1属性,add1的属性值是一个函数,为App.add()。所以会引用那个函数对象的地址,因此props.add1()的地址和App.add()的地址是一样的。
  2. 问题在于:App.add()这个函数里面调用了this.setState这个函数。在App.add()中,this就是指App,但是在被props.add1()引用的时候,this就变成了props(具体就是那个存在Box属性的对象)。
  3. 由于Box.props里面并没有setState()这个函数,所以必须在写add1属性的时候,就把add()的this绑定为App。
  4. .bind(this)就是这个目的。

如果不想写bind有没有办法呢?

有的,写bind主要是因为this会随着环境而变化,很麻烦。this就是js的糟粕,在es6出现的箭头函数,this不会再随着环境的变化而变化了,而是直接作为一个参数直接确定下来。也就是说,如果在class App里面申明一个箭头函数,箭头函数语句中出现的this,都是指App,所以就可以不用bind了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 作为一个合格的开发者,不要只满足于编写了可以运行的代码。而要了解代码背后的工作原理;不要只满足于自己的程序...
    六个周阅读 8,553评论 1 33
  • 目前,react组件有三种写法,分别是es5的createClass写法,es6的class写法,以及statel...
    ZoomFunc阅读 1,872评论 0 1
  • 前言 本文篇幅有点长,希望看完后能给你带去一些收获;主要针对react组件化原理、与vue开发感知上的对比以及一些...
    辣笔小明阅读 2,763评论 0 2
  • 生命周期流程图简单如下: 组件让你把用户界面分成独立的,可重复使用的部分,并且将每个部分分开考虑。React.Co...
    Simple_Learn阅读 1,117评论 0 0
  • 办公室是顶楼,白日里闷热难耐,却只有一台老旧的风扇呼呼的吹~ 打开桌旁的窗户透气,疲惫的时候望一望不远的南山,清澈...
    九月未了阅读 146评论 0 1