react第四天组件小实例

react初学day04

小项目

根据之前的内容我们已经可以写一个小项目,主要是钩子函数的使用
这是我们的运行截图,连接的是豆瓣的api,获取每个地区的电影,点击的时候,去请求对应地区的数据。样式是使用的bootstrap,通过jq的ajax请求数据
运行截图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>react</title>
    <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
    <script src="../js/react.min.js"></script>
    <script src="../js/react-dom.min.js"></script>
    <script src="../js/browser.min.js"></script>
    <script src="https://www.forgettime.cn/demo/js/jquery-1.10.1.min.js"></script>
    <!-- js文件按顺序引入,还有我们的jq和bootstrap-->
</head>
<style>
    .panel button{ margin: 0px 5px; }
    .list-group{ width: 40%; float: left; }
</style>
<body>
    <div id="app" class="container"></div>
    <script type="text/babel">
        let MovieBox = React.createClass({
            getDefaultProps(){     //设置我们的初始属性,也就是展现在页面上的五个按钮
                return {
                    citys:[
                        {id:1,title:"北京"},
                        {id:2,title:"上海"},
                        {id:3,title:"广州"},
                        {id:4,title:"深圳"},
                        {id:5,title:"青岛"},
                    ]
                }
            },
            getInitialState(){  //设置我们的初始属性,给选中哪个按钮设置一个参照值
                return {
                    activeIndex:1
                }
            },    //下面注销的代码稍后再说
            changeActiveIndex(index){ //这是第一种
                /*if(index === this.state.activeIndex){return false;}*/
                this.setState({
                    activeIndex: index
                })  //改变我们选中按钮所对应的id,在这个方法在点击按钮的时候触发
            },
            renderCity(){
                let {citys} = this.props; //解构的写法,类似于 let city = this.props.city
                let {activeIndex} = this.state;
                return citys.map((item)=>{ //我们没有v-for,只能通过map遍历数组,然后生成五个按钮
                    return (<button onClick={this.changeActiveIndex.bind(this,item.id)} className={"btn btn-default "+(item.id === activeIndex?'btn-danger':'')}>{item.title}</button>)
                }) //className这里,去判断activeIndex和当前按钮的id是否相同,相同就active
                //这里还有一个问题,changeActiveIndex这个方法需要穿一个参数,但是一写括号,就代表这里会触发,我们想的是,点的时候触发,但是又必须传参数,所以通过bind,既能够传参,又能让他在该触发的时候触发
            },
            getCity(){ //设置这个方法是因为,我们每次点击的时候请求的city是父组件传递
            //给子组件的,所以待会将这个方法传递给子组件,让子组件通过这个属性去确认到底请求哪个城市的数据
                let {citys} = this.props;
                let {activeIndex} = this.state;
                for(var i=0;i<citys.length;i++){
                    if(citys[i].id === activeIndex){
                        return citys[i].title;
                    }
                }
            },//这是第二种
            /* shouldComponentUpdate(nextProps,nextState){
                if(nextState.activeIndex === this.state.activeIndex){
                    return false;
                }
                return true;
            }, */
            render(){
                return (
                    <div className="panel panel-primary">
                        <div className="panel-heading">
                            {this.renderCity()}
                        </div>
                        <MovieList city={this.getCity()}/>   {/*将city传递给子组件*/}
                    </div>
                )
            }
        });

        let MovieList = React.createClass({
            getInitialState(){   
                return {
                    movie:[]
                }
            },//这是第三种
            componentWillReceiveProps(nextProps,nextState){
                /* if(nextProps.city === this.props.city){
                    return false;
                } */
                this.getMovie(nextProps.city)
            },
            componentDidMount(){   //在这里请求数据,当然每次点按钮的时候也要请求数据,即componentWillReceiveProps
                this.getMovie(this.props.city)
            },
            getMovie(city){//请求数据的方法
                $.ajax({
                    url:"https://douban.uieee.com//v2/movie/in_theaters",
                    data:{
                        city
                    },
                    dataType: "jsonp",   //解决jsonp格式的跨域的问题
                    success:(res)=>{
                        console.log(res);
                        this.setState({
                            movie:res.subjects
                        })
                    },
                    error:(err)=>{
                        console.log(err);
                    }
                })
            },
            renderList(){
                let{movie} = this.state;
                if(!movie){return false};
                return (
                    <ul className="list-group">
                        {movie.map((item)=>{
                            return (
                                <li className="list-group-item">{item.title}</li>
                            )
                        })}
                    </ul>
                )
            },
            render(){
                return (
                    <div className="panel-body">
                        {this.renderList()}
                    </div>
                )
            }
        })
        ReactDOM.render(<MovieBox/>,app);

    </script>
</body>
</html>

这样,我们的小实例就完成了,其实现在有个小问题,多次点击会重复请求数据。
有三种方法,已经在代码中标注

  1. 可以在更改activeId的时候直接判断,如果传入的id与activeId相同就不需要setState了
  2. 在MovieBox组件中shouldComponentUpdate里状态做出判断,如果更改的id一样的话就不用向下执行,就不会给MovieContent传入新的属性 nextState.city === this.state.city return false(父组件render没有执行)
  3. 在MovieContent组件中componentWillReceiveProps里属性判断之后再去获取最新的城市所对应的电影数据 nextProps.city===this.props.city return false;

任何一个都可以

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值