react-父子组件通信小demo

loading 2022年12月04日 52次浏览

实现一个页面,上面为导航栏,中间为内容,下面为tab栏(film,cinema,center)

  • tab栏点击后切换到对应页面且tab高亮
  • 导航栏中点击center按钮自动跳转到对应页面,且对应tab高亮
  • cinema页面读取网上提供的接口获取数据,并且实现模糊查询

1. cinema读取数据+模糊查询

具体实现看注释即可

注意此处实现了表单受控制组件,通过state进行管理表单

export default class cinema extends Component {
    state = {
        cinemaList: [],
        myText : ''
    }

    constructor() {
        super();
        //通过axios请求数据 填充影院列表
        axios({
            url: 'https://m.maizuo.com/gateway?cityId=110100&ticketFlag=1&k=9159391',
            methods: 'get',
            headers: {
                'X-Client-Info': '{ "a": "3000", "ch": "1002", "v": "5.2.1", "e": "167004825688003879895041", "bc": "110100" }',
                'X-Host': 'mall.film-ticket.cinema.list'
            }
            // 根据读取到的数据修改state
        }).then(res => {
            this.setState({
                cinemaList: res.data.data.cinemas,
            })
        })
    }

    render() {
        return (
            <div>
                {/* 通过state控制输入框内容 记得要搭配onChange*/}
                <input value={this.state.myText} onChange={this.inputFn}/>
                {
                    // 通过函数获取list并渲染出来
                    this.getCinemaList().map(item =>
                        <dl key={item.cinemaId}>
                            <dt>{item.name}</dt>                            
                        </dl>
                    )
                }
            </div>
        )
    }
    //根据输入内容修改state
    inputFn = (e) => {
        this.setState({
            myText : e.target.value
        })
    }
    //通过filter实现模糊查询
    getCinemaList(){
        return this.state.cinemaList.filter(item => item.name.includes(this.state.myText))
    }
}

2.tab栏和导航栏

先看大致的结构示意图

再看具体代码注释
父组件 包含了导航 内容 tabbar三个板块

export default class App extends Component {
    state = {
        list: [
            {
                id: 1,
                text: 'film'
            },
            {
                id: 2,
                text: 'cinema'
            },
            {
                id: 3,
                text: 'center'
            }
        ],
        current: 0
    }
    render() {
        return (
            <div>
                {/* 导航栏 */}
                <Navbar goToCenter={() =>{
                    this.setState({
                        current : 2
                    })
                }}></Navbar>

                {/* 根据state修改内容 */}
                {this.turnTab()}

                {/* 子组件传递新的index给该父组件 修改state为新的current 从而触发render重新根据turnTab()渲染内容 */}
                <TabBar getTabIndexFromSon = {(index) => {
                    this.setState({
                        current : index
                    })
                    // 传递state里的属性给子组件使用 避免在子组件中自己定义state
                }} current={this.state.current} list={this.state.list}></TabBar>
                
            </div>
        )
    }

    turnTab = () => {
        switch (this.state.current) {
            case 0: return <Film></Film>
            case 1: return <Cinema></Cinema>
            case 2: return <Center></Center>
            default: return null;
        }
    }
}

导航栏组件

export default class App extends Component {
    render() {
        return (
            <div style={{background:'lightblue',textAlign:'center',overflow:'hidden',height:'30px'}}>

                <button style={{float:'left'}}>back</button>

                <span>film demo</span>

                {/* 执行父组件传来的回调函数 通知父组件修改current */}
                <button style={{float:'right'}} onClick={() =>{
                    this.props.goToCenter()
                }}>center</button>

            </div>
        )
    }
}

tabbar组件

export default class tabBar extends Component {
    render() {
        return (
            <div>
                <ul>
                    {
                        this.props.list.map((item, index) =>
                            //每次修改state render会重新渲染 map就会从0开始重新遍历查看index是否匹配current 
                            <li key={item.id} className={this.props.current === index ? 'active' : ''} onClick={() => this.turnActive(index)}>
                                {item.text}
                            </li>
                        )
                    }
                </ul>
            </div>
        )
    }

    turnActive = (index) => {
        //在子组件中执行父组件传过来的回调函数 并将参数传回给父组件 通知父组件该修改新的current对应的content了
        this.props.getTabIndexFromSon(index);
    }
}