在 React.js 中,数据是从上自下流动(传递)的,也就是一个父组件可以把它的 state / props 通过 props 传递给它的子组件,但是子组件不能修改 props - React.js 是单向数据流,如果子组件需要修改父组件状态(数据),是通过回调函数方式来完成的

通过上节课的学习,已经把"小姐姐"组件做了一个基本的拆分,但是还不能实现随着输入,显示出输入的内容。这里涉及的是父组件向子组件传值。然后点击删除,就相当于子组件向父组件传值

父组件像子组件传值

这里只介绍最实用的,最快速的上手方法。就是使用组件属性的形式父组件给子组件传值。比如:我们在组件中加入content属性,然后给属性传递{item},这样就完成了父组件向子组件传值。

<XiaojiejieItem content={item} />

这时候可以通过this.props.xxx的形式进行接受,比如传递过来的值,可以用如下代码进行接收。

import React, { Component } from 'react'; //imrc
class XiaojiejieItem  extends Component { //cc

    render() { 
        return ( 
            <div>{this.props.content}</div>
         );
    }
}
export default XiaojiejieItem;

修改完小姐姐子项的组件后,可以打开浏览器进行预览了。试着添加几个新的选项试一下,比如躺式采耳…。

玩笑归玩笑,学到这里你要记住一点:父组件向子组件传递内容,靠属性的形式传递。

子组件向父组件传递数据

现在要作这样一个功能:点击组件中的菜单项后,删除改菜单项。在前边的课程中已经学习了这个知识,知识现在组件拆分了,就涉及了一个组件向父组件传递数据的知识需要掌握。

先来绑定点击事件,这时候当然是要在XiaojiejieItem组件中绑定了,代码如下:

import React, { Component } from 'react'; //imrc
class XiaojiejieItem  extends Component { //cc

    render() { 
        return ( 
            <div onClick={this.handleClick}>{this.props.content}</div>
         );
    }

    handleClick(){
        console.log('撩拨了小姐姐')
    }

}

export default XiaojiejieItem;

这时候进行预览,打开F12,再点击服务菜单项,就会再console里显示出"撩拨了小姐姐"的字样。但是console里还有一个warning警告,这个警告我们见过,就是要求循环时必须设置key值。

修改XiaoJieJie组件的render代码如下:

<ul>
    {
        this.state.list.map((item,index)=>{
            return (
                <XiaojiejieItem 
                key={index+item}  
                content={item} />
            )
        })
    }
</ul>

绑定成功后,现在就要通过操作子组件删除父组件里的数据了。但是React有明确规定,子组件时不能操作父组件里的数据的,所以需要借助一个父组件的方法,来修改父组件的内容。其实在以前已经写了一个删除方法deleteItem,现在要作的就是子组件调用这个方法。

//删除单项服务
deleteItem(index){
    let list = this.state.list
    list.splice(index,1)
    this.setState({
        list:list
    })

}

获取数组索引下标

那现在问题来了,要删除就要知道索引值,还是需要通过父组件传递给子组件.这里还是通过props属性的形式进行传递。

<ul>
    {
        this.state.list.map((item,index)=>{
            return (
                <XiaojiejieItem 
                key={index+item}  
                content={item}
                index={index} />
            )
        })
    }
</ul>

然后修改XiaojiejieItem组件,在handleClick方法里,写入下面代码:

handleClick(){
    console.log(this.props.index)
}

这时候预览一下,你会发现点击后报错,错误还是我们的老朋友,没有bind(this)。那可以用以前的老方法绑定this.

return ( 
    <div onClick={this.handleClick.bind(this)}>
        {this.props.content}
    </div>
);

这样是可以决解的,但是肯定会有小伙伴说,我看别人不是这样写的,而是在构造函数里绑定的。(有言曰:构造函数中绑定性能会高一些,特别是在高级组件开发中,会有很大的作用)

constructor绑定this方法。

import React, { Component } from 'react';
class xiaojiejieItem extends Component {
    constructor(props){
        super(props)
        // 绑定this
        this.handleClick = this.handleClick.bind(this)
    }
    render() { 
        return ( 
            // 点击事件            this.props.content 子接
        <li onClick = {this.handleClick}>{this.props.content}</li>
         );
    }
    //注意这里要使用箭头函数 或者 事件.bind(this)
    handleClick(){ 
        // 拿到索引值
        console.log(this.props.index)
        // 使用父组件传过来的删除方法  给其对应的index参数
        this.props.deletItem(this.props.index)

    }
}
 
export default xiaojiejieItem;

子组件调用父组件方法

如果子组件要调用父组件方法,其实和传递数据差不多,只要在组件调用时,把方法传递给子组件就可以了,记得这里也要进行this的绑定,如果不绑定子组件是没办法找到这个父组件的方法的。

<

ul>
    {
        this.state.list.map((item,index)=>{
            return (
                <XiaojiejieItem 
                key={index+item}  
                content={item}
                index={index}
                //关键代码-------------------start
                deleteItem={this.deleteItem.bind(this)}
                //关键代码-------------------end
                />
            )
        })
    }
</ul>

传递后,在XiaojiejieItem组件里直接hi用就可以了,代码如下:

handleClick(){
    this.props.deleteItem(this.props.index)
}

到此为止,就算是实现了子组件向父组件传值。特别提醒:这节课是React体系中非常重要的一节课,可以多听几遍,并进行练习。因为真正的React开发工作,每天写的就是各种组件,传值是组件之间产生联系的必要一环,无法跳跃。所以一定要学好。