React入门(三)之双向绑定

一、受控元素(组件)

简单概括,受控元素就是一个标签(组件)里用了react 里的东西。
比如,表单的value受控,受数据控制。

实例代码:

<script src="../js/react.js"></script>
<script src="../js/react-dom.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">

    //受控元素(组件)
    function getthing(){
        console.log('getthing');
    }

    let style_obj = {
        backgroundColor:'red'
    }

    ReactDOM.render(
        <div>
            <input type="button" value="点击" 
                 onClick={getthing} />,
            <p style={style_obj}>我是p</p>     
        </div>,
        document.getElementById('box')
    )

</script>

以上的 input , p 就是受控元素。

1.1、双向绑定

在vue里我们可以直接使用v-model对表单元素进行双向绑定,在react里没有指令,需要我们自己手动实现!

等等,我们还需要知道:
react中的onChange事件就是在用户输入的同时,就会被触发,相当于原生的input事件,所以会用onChange事件实现双向绑定。

以下我将针对四类表单元素进行双向绑定演示:

1)、单行文本框

//需要用到state
class Vom extends React.Component{
    constructor(){
        super();
        this.state = {
            textvalue:'',
        }
    }

    //文本框双向绑定
    changeText=(ev)=>{
        // this.state.textvalue = ev.target.value;
        console.log(this.state.textvalue);
        this.setState({
            textvalue:ev.target.value
        })
    }

    render(){
        return (
            <div>
                单行文本框:<input type="text" 
  value={this.state.textvalue} onChange={this.changeText} /><br/>
            </div>   
        ) 
    }
}

ReactDOM.render(
    <div>
        <Vom></Vom>   
    </div>,
    document.getElementById('box')
)

实现思路:

  • 在this.state里定义表单元素的初始值,为空;
  • 给表单元素绑定onChange事件及初始值;
  • 当用户输入内容,触发事件,在事件函数里通过ev.target.value修改this.state(即表单元素绑定的值);
  • setState函数会自动调用render函数重新渲染页面。

2)、单选框

class Vom extends React.Component{
    constructor(){
        super();
        this.state = {   
            sex:'女',        
        }
    }

    //单选框双向绑定
    changeSex=(ev)=>{
        console.log(55);
        console.log(ev.target.value);
        this.setState({
            sex:ev.target.value
        })
    }

    render(){
        return (
            <div>
                性别:<input type="radio" name="sex" 
    id="boy"  value="男" checked={this.state.sex=="男"} 
    onChange={this.changeSex}/>
    <label htmlFor="boy"></label>
                <input type="radio" name="sex" id="girl"  value="女"  
checked={this.state.sex=="女"} onChange={this.changeSex}/>
<label htmlFor="girl"></label><br/>
            </div>   
        ) 
    }
}

3)、下拉框

class Vom extends React.Component{
    constructor(){
        super();
        this.state = {
            per:'空姐',
        }
    }

    //下拉框双向绑定
    changePer=(ev)=>{
        this.setState({
            per:ev.target.value
        })
    }

    render(){
        return (
            <div>
                职业:<select onChange={this.changePer} value={this.state.per}>
                        <option value="程序员">程序员</option>
                        <option value="空姐">空姐</option>
                        <option value="司机">司机</option>
                        <option value="航天设计者">航天设计者</option>
                        <option value="自由人">自由人</option> 
                    </select>
            </div>   
        ) 
    }
}

4)、多选框

class Vom extends React.Component{
        constructor(){
            super();
            this.state = {
                power:['混吃等死']
            }
        }

        //多选框双向绑定
        changePower=(ev)=>{
            //由于此时获取的ev.target.checked值是点击后的结果
            var arr;
            if(!ev.target.checked){
                //若为false,需要删除
                arr = this.state.power;
                arr.splice(this.state.power.indexOf(ev.target.value),1)
            }else{
                //若为true,需要添加
                arr = [...this.state.power,ev.target.value]
            }
            this.setState({
                power:arr
            })
        }

        render(){
            return (
                <div>
                    技能:<input type="checkbox" name="" id="" checked={this.state.power.indexOf('敲代码')!=-1} value="敲代码" onChange={this.changePower}/>敲代码
                        <input type="checkbox" name="" id="" checked={this.state.power.indexOf('游泳')!=-1} value="游泳" onChange={this.changePower}/>游泳
                        <input type="checkbox" name="" id="" checked={this.state.power.indexOf('打游戏')!=-1} value="打游戏" onChange={this.changePower}/>打游戏
                        <input type="checkbox" name="" id="" checked={this.state.power.indexOf('混吃等死')!=-1} value="混吃等死" onChange={this.changePower}/>混吃等死
                        <input type="checkbox" name="" id="" checked={this.state.power.indexOf('睡觉')!=-1} value="睡觉" onChange={this.changePower}/>睡觉
                </div>   
            ) 
        }
    }

1.2、双向绑定的封装

可以为每个元素添加一个 name 属性(通常和数据名一致),处理函数根据 event.target.name 判断去做什么。

class Vom extends React.Component{
        constructor(){
            super();
            this.state = {
                textvalue:'',
                per:'空姐',
            }
        }

       changeInp=(ev)=>{
            this.setState({
                //键为变量时,加[]
                [ev.target.name]:ev.target.value
            })
       }

        render(){
            return (
                <div>
                    单行文本框:<input type="text" name="textvalue" value={this.state.textvalue} onChange={this.changeInp} /><br/>
                    职业:<select name="per" onChange={this.changeInp} value={this.state.per}>
                            <option value="程序员">程序员</option>
                            <option value="空姐">空姐</option>
                            <option value="司机">司机</option>
                            <option value="航天设计者">航天设计者</option>
                            <option value="自由人">自由人</option> 
                        </select>
                </div>   
            ) 
        }
    }

注意:多选框不适合这种封装。

二、非受控元素(组件)

默认值

​ 表单元素上的 value 将会覆盖 DOM 节点中的值,在非受控组件中,如果希望 React 能赋予组件一个初始值,但是不去控制后续的更新,指定一个 defaultValue 属性,而不是 value

三、生命周期及其钩子函数

react和vue一样,都有生命周期钩子函数。

react组件生命周期经历的阶段:初始化阶段 ------> 运行阶段(更新期)-----> 销毁阶段

3.1、初始化阶段 (挂载)

相当于vue中的 数据挂载+模板渲染 阶段。

组件实例被创建并插入 DOM 中时,其生命周期钩子函数的调用顺序如下:

1)、constructor

​ 构造函数里,可以做状态的初始化,接收props的传值

2)、componentWillMount:

在渲染前调用,相当于vue中的beforeMount

3)、render

渲染函数,不要在这里修改数据。 vue中也有render函数。

4)、componentDidMount 相当于vue中的 mounted

​ 渲染完毕,在第一次渲染后调用。之后组件已经生成了对应的DOM结构, 如果你想和其他JavaScript框架(swiper)一起使用,可以在这个方法中使用,包括调用setTimeout, setInterval或者发送AJAX请求等操作,相当于vue的mounted

class Vom extends React.Component{
     constructor(){
         super();
         this.state = {
             textvalue:'',
         }
         console.log('constructor');
     }

     componentWillMount(){
         console.log('componentWillMount');
     }

     componentDidMount(){
         console.log('componentDidMount');
     }
     
     render(){
         console.log('render');
         return (
             <div>
                 单行文本框:<input type="text" value={this.state.textvalue} onChange={this.changeText} /><br/>
             </div>   
         ) 
     }
 }

浏览器运行结果:

在这里插入图片描述

3.2、运行中阶段(更新)(相当于vue中更新阶段)

当组件的 props 或 state 发生变化时会触发更新(严谨的说,是只要调用了setState()或者改变了props时)。组件更新的生命周期调用顺序如下:

1)、shouldComponentUpdate(nextProps, nextState)

是否更新? 需要返回true或者false。如果是false,那么组件就不会继续更新了。

2)、componentWillUpdate,

即将更新。相当于vue中的 beforeUpdate

3)、 componentWillReceiveProps(nextProps):

在组件接收到一个新的 prop (更新后)时被调用。这个方法在初始化render时不会被调用。nextProps 是props的新值,而 this.props是旧值。

4)、render

​ 不要在这里修改数据

5)、componentDidUpdate

在组件完成更新后立即调用。在初始化时不会被调用。 相当于vue中的updated

class Vom extends React.Component{
        constructor(){
            super();
            this.state = {
                textvalue:'hhh ',
            }
        }
        changeText=()=>{
            this.setState({
                textvalue:'哈哈哈'
            })
        }
        shouldComponentUpdate(){
            
            console.log('shouldComponentUpdate');
            return true;
        }

        componentWillUpdate(){
            console.log('componentWillUpdate');
        }
        
        componentWillReceiveProps(){
            console.log('componentWillReceiveProps');
        }

        componentDidUpdate(){
            console.log('componentDidUpdate');
        }

        render(){
            console.log('render');
            return (
                <div> 
                    <p>{this.state.textvalue}</p>
                    <input type="button" onClick={this.changeText} value="点击改变值"/>
                </div>   
            ) 
        }
    }

在这里插入图片描述

3.3、销毁阶段(卸载)

componentWillUnmount()

即将卸载,可以做一些组件相关的清理工作,例如取消计时器、网络请求等

注意:

父更新则子更新,子更新父不更新

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值