【React】react input输入的时候输入一次就失去焦点,需要再次点击才能输入一次
如题,每次点击input的时候才能输入一次
查看了代码,原因应该是当我每次输入触发onChange的时候DOM重绘,但是根源并不清楚到底是什么,望指教;
因为是第一次用react,所以有什么问题大家也可以提出来,让我改进一下,谢谢!
代码如下
class Goods extends Component {
constructor() {super();
this.state = {
id: '',
name: '',
orderBy_id: 3,// 排序
isFilter: false,
type: '',//类型
page_num: 1, // 页码
min_price: '', // 最低价
max_price: '', // 最高价
screen_id: '', // 筛选选择类型
str: ''
};
this.changeSort = this.changeSort.bind(this);
this.changeProd = this.changeProd.bind(this);
this.selectedAttr = this.selectedAttr.bind(this);
this.resetAttr = this.resetAttr.bind(this);
this.selectedFilter = this.selectedFilter.bind(this);
this.changePrice = this.changePrice.bind(this);
this.closeModal = this.closeModal.bind(this);
}
changePrice(event) {
const target = event.target;
if(target.name === 'min_price') {
this.setState({
min_price: event.target.value
})
}else {
this.setState({
max_price: event.target.value
})
}
}
render() {
const {data} = this.props;
const SelectWrapper = () => {
return (
<TopWrapper>
<TopItem className={(this.state.orderBy_id === 3 && !this.state.isFilter) ? 'selected' : ''}
onClick={(e) => this.changeSort(e, 'other', 3)}>
<span className='text'>综合</span>
</TopItem>
<TopItem className={(this.state.orderBy_id === 5 && !this.state.isFilter) ? 'selected' : ''}
onClick={(e) => this.changeSort(e, 'other', 5)}>
<span className='text'>销量</span>
</TopItem>
<TopItem
className={((this.state.orderBy_id === 2 || this.state.orderBy_id === 1) && !this.state.isFilter) ? 'selected' : ''}
onClick={(e) => this.changeSort(e, 'price')}>
<span className='text'>价格</span>
<span className='icon'>
<i className={`iconfont icon-shangjiantou ${this.state.orderBy_id === 2 ? 'selected' : ''}`}></i>
<br/>
<i className={`iconfont icon-xiajiantou ${this.state.orderBy_id === 1 ? 'selected' : ''}`}></i>
</span>
</TopItem>
<TopItem className={this.state.isFilter ? 'selected' : ''}
onClick={(e) => this.changeSort(e, 'shaixuan')}>
<span className='text'>筛选</span>
<span className='icon'>
<i className='iconfont'></i>
<br/>
<i className={`iconfont icon-xiajiantou ${this.state.isFilter ? 'selected' : ''}`}></i>
</span>
</TopItem>
</TopWrapper>
)
};
const ProductContainers = () => {
let isSelf = (type) => {
if(type === '1') {
return (
<span>自营</span>
)
}
return null;
};
if(!data.length){
return null
}
return (
<ProductWrapper>{
data.map((item, index) => {
return (
<ProductItem key={index}>
<div className='img'>
<img src={item.image} alt=""/>
</div>
<p className='name'>
{
isSelf(item.support_type)
}
{item.name}
</p>
<p className='price'>¥
<span>
{(item.price).toFixed(2)}
</span>
</p>
</ProductItem>
)
})
}
</ProductWrapper>
)
};
const FilterContainer = () => {
const {isFilter, screen_id, min_price, max_price} = this.state;
const {options} = this.props;
if(isFilter) {
return (
<FilterWrapper>
<div className='content'>
<p className='title'>聚鲨服务</p>
<ul>
{
options.map((item, index) => {
if(screen_id.indexOf(item.id) > -1) {
return (
<li key={index} onClick={() => {this.selectedAttr(item.id)}} className='screen-select'>{item.name}
<img className='selected' src='http://wp.ghs.net/static/img/selectBg.png' alt=""/>
</li>
)
}else {
return (
<li key={index} onClick={() => {this.selectedAttr(item.id)}}>{item.name}</li>
)
}
})
}
</ul>
<p className='title'>价格区间</p>
<p className='price-range'>
<input type="text" name='min_price' placeholder='最低价' onChange={this.changePrice} value={min_price} />
<span>-</span>
<input type="text" name='max_price' placeholder='最高价' onChange={this.changePrice} value={max_price}/>
</p>
<div className='buttons'>
<p className='reset' onClick={this.resetAttr}>重置条件</p>
<p className='sure' onClick={this.selectedFilter}>确定</p>
</div>
</div>
<div className='model' onClick={this.closeModal}></div>
</FilterWrapper>
)
}
return null
};
return (
<Wrapper>
<SelectWrapper/>
<FilterContainer />
<ProductContainers/>
</Wrapper>
)
}
}
回答
应该是在循环中的 key
值使用了 index
的缘故吧。
由于 React
中的 diff
算法需要通过 key
值判断前后的虚拟 dom
是否发生了改变,加上 index
的值会动态改变的缘故,所以会导致 dom
重绘。
之前,我在循环中产生了包含 input
的 dom
结构,并使用了时间戳作为 key
值出现了同样的情况。
任何情况下建议给 key
一个固定唯一的值。
I hope this will help you.
不要在你的render中
return的时候有分支判断。
比如你的if(isFilter). 这是一种不好的实践,并且很容易有各种问题,包括你的这个问题。
你现在相当于在render里又定义了3个子组件
把render里的组件<SelectWrapper/> <FilterContainer /> <ProductContainers/>
拿到外面去,或者把他们写成一个方法放Goods里
import React from 'react';
import {render} from 'react-dom';
const mountPoint = document.createElement('div');
mountPoint.setAttribute('id', 'root');
document.body.appendChild(mountPoint);
class Goods extends React.Component {
constructor() {
super();
this.state = {
id: '',
name: '',
orderBy_id: 3,// 排序
isFilter: false,
type: '',//类型
page_num: 1, // 页码
min_price: '', // 最低价
max_price: '', // 最高价
screen_id: '', // 筛选选择类型
str: ''
};
this.changePrice = this.changePrice.bind(this);
}
changePrice(event) {
const target = event.target;
console.log(event.target.value)
if(target.name === 'min_price') {
this.setState({
min_price: event.target.value
})
}else {
this.setState({
max_price: event.target.value
})
}
}
filterContainer() {
const {isFilter, screen_id, min_price, max_price} = this.state;
return (
<div>
<div className='content'>
<p className='title'>聚鲨服务</p>
<p className='title'>价格区间</p>
<p className='price-range'>
<input type="text" name='min_price' placeholder='最低价' onChange={this.changePrice} value={min_price} />
<span>-</span>
<input type="text" name='max_price' placeholder='最高价' onChange={this.changePrice} value={max_price}/>
</p>
</div>
</div>
)
};
render() {
return (
<div>
{this.filterContainer()}
<p>min_price:{this.state.min_price}</p>
<p>max_price:{this.state.max_price}</p>
</div>
)
}
}
render(
<Goods />,
mountPoint
);
请问楼主解决这个问题了么 我今天也遇到了
这个原因是使用了高阶组件的原因,至于原因具体还不清楚,应该是修改状态的时候,重新执行render()方法,而你的输入框是写在高阶组件里面的,所以会导致重新执行你的高阶组件的那个方法,去重新渲染你的整个高阶组件,应该是react,diff算法的一个bug吧!
以上是 【React】react input输入的时候输入一次就失去焦点,需要再次点击才能输入一次 的全部内容, 来源链接: utcz.com/a/72244.html