ref
使用中的坑
小结:
- setState是异步函数
所以关于dom的操作需要在setState的回调中
比如现在我们要用ref绑定取得要服务的数量,可以先用ref
进行绑定。- ref可以绑定到dom
<ul ref={(ul)=>{this.ul=ul}}>
{
this.state.list.map((item,index)=>{
return (
<XiaojiejieItem
key={index+item}
content={item}
index={index}
deleteItem={this.deleteItem.bind(this)}
/>
)
})
}
</ul>
绑定后可以在addList()
方法中,获取当前<div>
的值.
addList(){
this.setState({
list:[...this.state.list,this.state.inputValue],
inputValue:''
})
//关键代码--------------start
console.log(this.ul.querySelectorAll('div').length)
//关键代码--------------end
}
这时候你打开控制台,点击添加服务按钮,你会返现数量怎么少一个?(就是这个坑),其实这个坑是因为React中更多setState
是一个异步函数所造成的。也就是这个setState
,代码执行是有一个时间的,如果你真的想了解清楚,你需要对什么是虚拟DOM有一个了解。简单的说,就是因为是异步,还没等虚拟Dom渲染,我们的console.log
就已经执行了。
那这个代码怎么编写才会完全正常那,其实setState
方法提供了一个回调函数,也就是它的第二个函数。下面这样写就可以实现我们想要的方法了。
addList(){
this.setState({
list:[...this.state.list,this.state.inputValue],
inputValue:''
//关键代码--------------start
},()=>{
console.log(this.ul.querySelectorAll('div').length)
})
//关键代码--------------end
}
- html 的类要写成
className
- 组件最外层只能有一个html标签,可以用
<Fragment>
解决
JSX中的html
解析问题
如果想在文本框里输入一个<h1>
标签,并进行渲染。默认是不会生效的,只会把<h1>
标签打印到页面上,这并不是我想要的。如果工作中有这种需求,可以使用dangerouslySetInnerHTML
属性解决。具体代码如下:
<ul>
{
this.state.list.map((item,index)=>{
return (
<li
key={index+item}
onClick={this.deleteItem.bind(this,index)}
dangerouslySetInnerHTML={{__html:item}}
>
</li>
)
})
}
</ul>
上面的代码就可以实现html
格式的输出。
JSX中<label>
标签的坑
JSX中<label>
的坑,也算是比较大的一个坑,label是html
中的一个辅助标签,也是非常有用的一个标签。
先看下面的代码,我们在文本框前面加入一个<label>
。
<div>
<label>加入服务:</label>
<input className="input" value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button onClick={this.addList.bind(this)}> 增加服务 </button>
</div>
这时候想点击“加入服务”直接可以激活文本框,方便输入。按照html
的原思想,是直接加ID就可以了。代码如下:
<div>
<label for="jspang">加入服务:</label>
<input id="jspang" className="input" value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button onClick={this.addList.bind(this)}> 增加服务 </button>
</div>
这时候你浏览效果虽然可以正常,但console
里还是有红色警告提示的。大概意思是不能使用for
.它容易和javascript里的for循环混淆,会提示你使用htmlfor
。
<div>
<label htmlFor="jspang">加入服务:</label>
<input id="jspang" className="input" value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
<button onClick={this.addList.bind(this)}> 增加服务 </button>
</div>
这时候代码就正确了,可以实现点击<label>
后,激活<input>
标签了。
网友评论