ThinkChat2.0新版上线,更智能更精彩,支持会话、画图、阅读、搜索等,送10W Token,即刻开启你的AI之旅 广告
# 双向数据绑定 ## 第一种方法:重点推荐 对组件身上添加 ref属性,且设置值a。在setState功能中使用 this.refs.a就可以直接获取元素。 ```javascript <input ref="input" type="text" defaultValue={this.state.msg} onChange={this.changeValue.bind(this)} /> changeValue(event){ this.setState(()=>{ return { msg:this.refs.input.value } }) } ``` ## 第二种方法: 通过事件对象e传递 e.target.value直接 书写会有错误,[https://reactjs.org/docs/events.html#event-pooling。解决办法](https://reactjs.org/docs/events.html#event-pooling%E3%80%82%E8%A7%A3%E5%86%B3%E5%8A%9E%E6%B3%95) 两种 1. 直接在setState方法外面,先把值存储好,再使用 这个值就可以,推荐 ```javascript changeValue(event){ var value = event.target.value; this.setState(()=>{ return { msg:value } }) } ``` 2. 通过在setState方法外面,书写e.persist()方法,进行保护就可以。建议少用 ```javascript changeValue(event){ event.persist() this.setState(()=>{ return { msg:event.target.value } }) } ``` ## 第三种方法 对组件添加id名称,获取元素的value值即可.最不推荐 ```javascript <input id="box" type="text" defaultValue={this.state.msg} onChange={this.changeValue.bind(this)} /> changeValue(event){ this.setState(()=>{ return { msg:document.getElementById('box').value } }) } ``` # 下面为分析具体分析和操作 ## 新建src/components/BridgeLink.js组件 BridgeLink.js准备一个输入框,以及一个私有数据,当用户在表单中输入数据,那么相应的私有数据也应该改变。 ~~~ import React,{Component} from 'react' export default class BridgeLink extends Component{ constructor(props){ super(props) this.state={ msg:'你好' } } render() { return <div> <input /> <span>{this.state.msg}</span> </div> } } ~~~ 我们给表单书写属性值绑定数据。 ~~~ <input value={this.state.msg}/> ~~~ ![](https://box.kancloud.cn/48ba930afd40ed67e9ce94ae1e9c173f_224x50.png) # f12控制台 ``` Warning: Failed prop type: You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`. 警告:失败的属性类型:您为没有“onchange”处理程序的表单字段提供了“value”属性。这将呈现只读字段。如果字段应该是可变的,请使用“defaultvalue”。否则,设置“onchange”或“readonly”。 ``` 这里的意思是如果期望表单书写value属性那么必须有onchange事件。 ~~~ changeMsg(){ } …… <input onChange={this.changeMsg.bind(this)} value={this.state.msg}/> ~~~ ![](https://box.kancloud.cn/31bbe5f4dc52dd8ed98fbefe3fa6a804_899x189.gif) 我们发现在输入框不断的输入不会发生任何的改变。我们也明白了,React 默认不会直接对数据进行双向数据绑定。如果想要改变state的msg数据人能通过this.setState来改变数据。 # 将state中的msg数据修改为表单的值 > 我们要获取到表单的值如何获取? > 有三种方法 > 1.通过React操作dom的方式 refs(推荐又简单又好做) > 2.通过事件对象。通过e.target.value (次推荐) > 3.通过ID 操作原生DOM来获取到表单的值(最low) ## 第一种 推荐使用其实和vue中的$refs很相似。通过`this.$refs.my`来获取元素.value来获取表 ~~~ changeMsg(e){ this.setState((state,props)=>{ return {msg:this.refs.my.value} }) } …… <input ref="my" onChange={this.changeMsg.bind(this)} id="input" value={this.state.msg}/> ~~~ ## 第二种 最麻烦,而且是有问题的,在使用时千万要小心,请按照步骤去做。 通过事件对象e传递 e.target.value直接 书写会有错误,[https://reactjs.org/docs/events.html#event-pooling](https://reactjs.org/docs/events.html#event-pooling)。解决办法 两种 ~~~ changeMsg(e){ console.log(e.target.value) } …… <input onChange={this.changeMsg.bind(this)} value={this.state.msg}/> ~~~ ![](https://box.kancloud.cn/1f7e12e014d959dd22da5cf2c361741b_901x234.gif) ~~~ changeMsg(e){ console.log(e.target.value) this.setState({ msg:e.target.value }) } …… <input onChange={this.changeMsg.bind(this)} value={this.state.msg}/> ~~~ ![](https://box.kancloud.cn/43f1379d5bed5814ab0e2fc38d2d90e9_918x206.gif) 看到上面的结果我们觉得是达到目的了。不过我们使用this.setState()的这种方法是直接操作的。还有另外一种写法 ~~~ this.setState((state,props)=>{ return { msg: e.target.value} }) ~~~ 我们来尝试一下直接报错 ``` react-dom.development.js:506 Warning: This synthetic event is reused for performance reasons. If you're seeing this, you're accessing the property `target` on a released/nullified synthetic event. This is set to null. If you must keep the original synthetic event around, use event.persist(). See https://fb.me/react-event-pooling for more information. ``` 注意这种更改私有数据state的方法,许多人都在用。那么为什么它不可以呢?我们可以稍微的修改一下代码 ~~~ changeMsg(e){ console.log(e.target.value) this.setState((state,props)=>{ console.log(e.target) // return { msg: e.target.value} }) } ~~~ ![](https://box.kancloud.cn/40cbd22ea2463f26be6529261ccf595a_1060x193.gif) 我们发现结果为null那么如何解决这个问题呢? 有两种办法 ### 第一种解决办法 我们发现在this.setState的外面方问e.target.value居然有值,在this.setState内部竟然得不到值。我们可以在外面先把值保存起来,再去使用这个值,修改如下 ~~~ changeMsg(e){ console.log(e.target.value) var value = e.target.value this.setState((state,props)=>{ return { msg: value} }) } ~~~ ![](https://box.kancloud.cn/45e3d4dc62348e8a9ac3a871aa0b12d0_912x190.gif) ### 第二种解决办法 这个解决办法是官方提供的,根据报错的提示中我们有发现它让我们使用event.persist(),来将事件对象一直保持。 其实React在this.setState方法体中它已经将事件对象重新进行修改。不过也提供了方法如果你不期望被修改一直保持,就需要使用上面的给出的event.persist();不过这种方法不常用。 ~~~ changeMsg(e){ e.persist(); this.setState((state,props)=>{ return { msg: e.target.value} }) } ~~~ ## 第三种 ~~~ changeMsg(){ console.log(document.getElementById('input').value) } …… <input onChange={this.changeMsg.bind(this)} id="input" value={this.state.msg}/> ~~~ ![](https://box.kancloud.cn/32cf98970b88876d32cc4b9e4ea282cb_908x160.gif) 我们发现我们是可以取到表单的数据了。接下来就是将表单的值与私有数据的msg进行同步。 ~~~ changeMsg(){ console.log(document.getElementById('input').value) this.setState({ msg:document.getElementById('input').value }) } …… <input onChange={this.changeMsg.bind(this)} id="input" value={this.state.msg}/> ~~~ ![](https://box.kancloud.cn/95df7041a5b2604603b650f109a15bd5_798x233.gif) # 总结 对于React的双向数据绑定,重点掌握。 1.对于设置数据有两种操作方式`this.setState({})`和`this.setState((state,props)=>{ return {} })`两种都要知道,工作中的话,使用任意一种都可以,为了工作方便**建议掌握后者**,因为操作起来便利。 2.着重掌握`refs`操作dom的方式。