在工作中用antdDesign UI组件写Input表单的时候,发现需要同时设置默认值和用户可以手动输入改变值(修个表的数据),发现搞不清defaultValue和value的作用,能否同时使用?彼此是否会产生影响?编译是否会报错?
表单元素有这么几种属于状态的属性:
对于设置了上面提到的对应“状态属性“值的表单元素就是受控表单组件,比如:
//创建组件
class Login extends React.Component{
//初始化状态
state = {
username:'', //用户名
password:'' //密码
}
//保存用户名到状态中
saveUsername = (event)=>{
this.setState({username:event.target.value})
}
//保存密码到状态中
savePassword = (event)=>{
this.setState({password:event.target.value})
}
//表单提交的回调
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {username,password} = this.state
alert(`你输入的用户名是:${username},你输入的密码是:${password}`)
}
render(){
return(
<form onSubmit={this.handleSubmit}>
用户名:<input onChange={this.saveUsername} type="text" name="username"/>
密码:<input onChange={this.savePassword} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
和受控组件相对,如果表单元素没有设置自己的“状态属性”,或者属性值设置为 null,这时候就是非受控组件。
它的表现就符合普通的表单元素,正常响应用户的操作。
//创建组件
class Login extends React.Component{
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {username,password} = this
alert(`你输入的用户名是:${username.value},你输入的密码是:${password.value}`)
}
render(){
return(
<form onSubmit={this.handleSubmit}>
用户名:<input ref={c => this.username = c} type="text" name="username"/>
密码:<input ref={c => this.password = c} type="password" name="password"/>
<button>登录</button>
</form>
)
}
}
引入受控组件不是说它有什么好处,而是因为 React 的 UI 渲染机制,对于表单元素不得不引入这一特殊的处理方式。
在浏览器 DOM 里面是有区分 attribute 和 property 的。
attribute 是在 HTML 里指定的属性,而每个 HTML 元素在 JS 对应是一个 DOM 节点对象,这个对象拥有的属性就是 property(可以在 console 里展开一个 DOM 节点对象看一下,HTML attributes 只是对应其中的一部分属性),attribute 对应的 property 会从 attribute 拿到初始值,有些会有相同的名称,但是有些名称会不一样,比如 attribute class 对应的 property 就是 className。
(详细解释:.prop,.prop() vs .attr())
回到 React 里的 <input> 输入框,当用户输入内容的时候,输入框的 value property 会改变,但是 value attribute 依然会是 HTML 上指定的值(attribute 要用 setAttribute 去更改)
。
React 组件必须呈现这个组件的状态视图,这个视图 HTML 是由 render 生成,所以对于
render: function() {
return <input type="text" value="hello"/>;
}
在任意时刻,这个视图总是返回一个显示 hello 的输入框。
如果input 表单只是显示默认值,不会手动去修改该值,则值需要使用defaultValue,
如果需要获取用户输入的值,则一定要用value属性,但是一定要配合onchange事件一起使用,否则值是不会变的
<Input placeholder="选择规格属性名称" defaultValue={item.title} value={item.title} readOnly className={styleObj["width-360"]}/>
<Input defaultValue={text} value={text} onChange={that.tableInputChange.bind(that, record,'price')}/>
如果设置了value的值,则要么添加
onChange
事件要么添加readOnly
属性,否则编译器会提示报错