我创建了一个 React 应用程序。它在 IE、Opera、Chrome、FF 中按预期工作。我在状态更新后在 Edge 中渲染一个组件时遇到问题。我无法帮助自己使用 React Devtools for Chrome,因为它应该在那里工作。
我的组件是两个输入字段的组合。一种是数字输入,可以由用户操作,另一种显示相同的数字值,但格式为货币字符串。当用户单击该字段时,具有格式化值的字段将隐藏并显示非格式化输入字段。当用户离开可编辑输入时,之前隐藏的输入再次显示。
因为每次onchange
触发事件时状态都会改变,我希望其他输入也会在 each 和 every 上更新onchange
。这是因为它被隐藏了吗?
这是代码,我尽量简化它:
class MasterComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
Rows: [
{ Id: 1, Name: 'Row 1', Price: 11 },
{ Id: 2, Name: 'Row 2', Price: 21 },
{ Id: 3, Name: 'Row 3', Price: 13 }
]
}
this.changeObjectValue = this.changeObjectValue.bind(this);
}
render() {
return <MCVE changeObjectValue={this.changeObjectValue} rows={this.state.Rows}></MCVE>
}
changeObjectValue(rowId, propertyName, value) {
// define which list user wants to change
let list = this.state['Rows'];
let changedList = [];
// change value
list.forEach(element => {
if (element.Id == rowId) {
element[propertyName] = value;
}
changedList.push(element);
});
// dynamically set objct name frmo parameters
this.setState({ Rows: changedList });
}
}
class MCVE extends React.Component {
render() {
return <table>
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Price</th>
</tr>
</thead>
<tbody>
{this.props.rows.map((r, index) =>
<tr key={r.Id}>
<td>
<input readOnly value={r.Id}></input>
</td>
<td><input name="Name" onChange={event => this.changeInput(event, r.Id)} value={r.Name}></input></td>
<td>
<input name="Price" className="edit" type="hidden" onBlur={event => toggleEditDisplay(event)} onChange={event => this.changeInput(event, r.Id)} value={r.Price}></input>
<input name="Price" className="display" readOnly onClick={event => toggleEditDisplay(event)} value={formatMoney(r.Price)}></input>
</td>
</tr>
)}
</tbody>
</table>
;
}
changeInput(event, rowId) {
let propertyName = event.target.name;
this.props.changeObjectValue(
rowId,
propertyName,
event.target.value);
}
}
function toggleEditDisplay(event) {
let el = event.target;
// if has class 'edit' else has class 'display'
if (el.className.split(/\s+/).filter(e => e == 'edit').length > 0) {
let elToToggle = el.parentElement.getElementsByClassName('display')[0];
el.type = "hidden";
elToToggle.type = "text";
}
else {
let elToToggle = el.parentElement.getElementsByClassName('edit')[0];
el.type = "hidden";
elToToggle.type = "number";
}
}
function formatMoney(amount, decimalCount = 2, decimal = ",", thousands = ".", currencySymbol = '€', ignoreCurrencySymbol = false) {
try {
decimalCount = Math.abs(decimalCount);
decimalCount = isNaN(decimalCount) ? 2 : decimalCount;
const negativeSign = amount < 0 ? "-" : "";
let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(decimalCount)).toString();
let j = (i.length > 3) ? i.length % 3 : 0;
return negativeSign + (j ? i.substr(0, j) + thousands : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands) + (decimalCount ? decimal + Math.abs(amount - i).toFixed(decimalCount).slice(2) : "") + (ignoreCurrencySymbol ? "" : currencySymbol);
} catch (e) {
console.log(e)
}
};
ReactDOM.render(<MasterComponent />, document.getElementById('app'));
最低 HTML:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<div id="app"></div>
<script src="https://unpkg.com/react@16/umd/react.development.js" crossorigin></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js" crossorigin></script>
<script src="reactScript.js"></script>
</body>
</html>