目录
原生html元素
原生html是不存在双向绑定的
!以input标签举例说明
input属性
- value:当前表单元素的值
- onchange:失去焦点且值发生改变时触发
示例1
<input type="text" value="111">
上述代码在页面显示结果如下:
示例2
在案例1上稍作修改
<input id='inputbox' type='text'/>
<button id="btnbox">点击修改value值</button>
<script>
const inputele = document.getElementById('inputbox')
const btnele = document.getElementById('btnbox')
// 赋值-在页面显示如案例1
let inputvalue = '111'
inputele.value = inputvalue
// 修改inputvalue值 -> 通过代码修改
// 页面没有发生变化 -> 不会重新渲染
btnele.onclick = function(){
inputvalue = '222'
console.log(inputvalue) // 222
}
//修改value值为11111 -> 在页面修改元素的value属性值
// -> 页面变化,但是inputvalue变量值并没有发生变化
inputele.onchange = function(e){
console.log(e.targe.value) // 11111
console.log(inputvalue) // 111
}
</script>
- 通过上述案例可以看出页面发生改变不会更改变量的值,变量的值改变不会让页面变化 -> 原生input标签的value属性不存在双向绑定
- 上述代码的赋值
其实本质就是let inputvalue = '111' inputele.value = inputvalue
赋值之后就和原来的 inputvalue属性不存在关联关系了,相当于赋了一个inputele.value = '111'
默认值
,因此 -> 修改inputvalue属性值不会影响元素的value属性,修改value属性也不会影响inputvalue属性值。
react中
在react中也不存在双向绑定
!每次更新页面和值都需要我们自己去调用指定的api来触发。
受控组件与非受控组件
属性
react中的input
- defaultValue属性:默认值
- value属性:当前表单元素的值
- onChange: 表单元素值改变时触发
error - input标签value属性使用
- 今天想添加一个input标签,默认值为222,代码如下:
function Mycomponent(){ return ( <ul> <li><input value=‘222’/></li> </ul> ) } ReactDOM.render(<Mycomponent />, document.getElementById('test'))
- 报错如下
- 错误: 在react中input标签存在value元素则表示元素为
受控组件
,需要添加onChange方法 - 原因: 在react中 没有 添加onChange方法的input标签为只读的,不能添加value 属性。 若是想添加默认值可以 使用
defaultValue
属性
- 错误: 在react中input标签存在value元素则表示元素为
- 修正
function Mycomponent(){ return ( <ul> <li><input defaultValue='222' /></li> </ul> ) } ReactDOM.render(<Mycomponent />, document.getElementById('test'))
示例 - useState
案例1:如上图,表格数据,每次重新获取之后都要更新组件页面,因此需要使用useState hook定义数据
import { useState, useEffect } from "react"
import { Table } from 'antd'
export default function UseDefaultValue (){
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
]
const [data,setData] = useState({}) // 存储表格数据
function getList(){
// 模拟接口获取表格数据
setTimeout(()=>{
const res = {
list:[
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
{
key: '2',
name: '胡彦祖',
age: 42,
address: '西湖区湖底公园1号',
}
],
count:2
}
setData({
count: res.count,
list:res.list
})
},200)
}
useEffect(()=>{
getList()
},[])
return(
<div>
<Table dataSource={data.list} columns={columns} />
</div>
)
}
示例 - input标签defaultValue属性+ useRef
案例1:如上图,现在存在模糊查询,通过搜索关键字筛选符合条件的表格列表数据
- 此时变量可以使用
uesRef
定义 ,使用defaultValue
属性进行赋值- [1] defaultValue属性为默认值,当在页面输入搜索关键字时页面自动发生变化 并且 可以通过onChange事件获取用户输入的值来调用接口获取数据;
- [2] 我们并没有通过代码修改 属性值,不需要回显数据,因此使用uesRef定义数据即可;
import { useRef, useState, useEffect } from "react"
import { Table } from 'antd'
export default function UseDefaultValue (){
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
]
const paramsData = useRef({
keyword:'',
page:1,
size:10
})
const [data,setData] = useState({}) // 存储表格数据
function getList(){
// 模拟接口获取表格数据
setTimeout(()=>{
console.log('params', paramsData.current)
const res = {
list:[
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
},
{
key: '2',
name: '胡彦祖',
age: 42,
address: '西湖区湖底公园1号',
}
],
count:2
}
setData({
count: res.count,
list:res.list
})
},200)
}
useEffect(()=>{
getList()
},[])
return(
<div>
<input
type="text"
placeholder="请输入搜索关键字"
defaultValue={paramsData.current.keyword}
onChange={ e =>{
paramsData.current.keyword = e.target.value
// 重新获取数据
getList()
}}
/>
<Table dataSource={data.list} columns={columns} />
</div>
)
}
示例 - input标签defalutValue属性重新赋值
案例:如上图,存在一个编辑框,点击右侧编辑框更改编辑框数据
import { useRef } from "react"
import { Button } from 'antd'
export default function UseDefaultValue (){
const paramsData = useRef({
keyword:'',
page:1,
size:10
})
return(
<div>
<input
type="text"
placeholder="请输入搜索关键字"
defaultValue={paramsData.current.keyword}
onChange={ e =>{
paramsData.current.keyword = e.target.value
// 重新获取数据
}}
/>
<Button type='link' onClick={()=>{
paramsData.current.keyword = '222222'
}}>更改输入框数据</Button>
</div>
)
}
- 显而易见,在点击按钮时页面数据并不会改变
- 数据使用的 hook useRef,值发生改变时不会更新组件!
- 数据使用的 hook useRef,值发生改变时不会更新组件!
import { useState } from "react"
import { Button } from 'antd'
export default function UseDefaultValue (){
const [num, setNum] = useState(0);
return (
<>
<input defaultValue={num} />
<Button onClick={() => setNum(666)}>Button</Button>
</>
)
}
- 在上述代码中使用的 hook useState 定义数据,感觉在点击按钮时页面数据会发生变改,但是实际并没有改变, 此时需要在元素上添加
key值
import { useState } from "react"
import { Button } from 'antd'
export default function UseDefaultValue (){
const [num, setNum] = useState(0);
return (
<>
<input defaultValue={num} key={num}/>
<Button onClick={() => setNum(666)}>Button</Button>
</>
)
}
原因
这需要看一下渲染逻辑:
- 初始化时:
- react 内部会获取传入的 defaultValue,然后同时挂载到 node 的 value 和 defaultValue上,这样初次渲染的时候页面就会展示传入的默认属性;
- 给组件的每个元素添加一个key值
- 更新时:
- 比较key值,key值相同 -> 复用;key值不同 -> 重新创建元素
示例 - input标签defalutValue属性重新赋值-弹框编辑
案例1:现在存在如上表格数据,点击按钮显示弹框进行编辑
import { useRef, useState, useEffect} from "react"
import { Table, Button, Select, Modal} from 'antd'
export default function UseDefaultValue (){
const classObj = {
1: '七年级1班',
2: '七年级2班',
3: '七年级3班',
4: '八年级1班',
5: '八年级2班',
6: '九年级1班'
}
const columns = [
{
title: '姓名',
dataIndex: 'name',
key: 'name',
},
{
title: '年龄',
dataIndex: 'age',
key: 'age',
},
{
title: '住址',
dataIndex: 'address',
key: 'address',
},
{
title:'班级',
dataIndex: 'class',
key: 'class',
render: value => classObj[value]
},
{
title:'编辑',
dataIndex:'key',
key:'key',
render:(id,value) => (
<Button type='link' onClick={()=>{
itemInfo.current = value
setodalOpen(true)
}}>编辑班级</Button>
)
}
]
const paramsData = useRef({
keyword:'',
page:1,
size:10
})
const [data,setData] = useState({}) // 存储表格数据
const [isModalOpen, setodalOpen]= useState(false) // 是否编辑
const itemInfo = useRef({})
function getList(){
// 模拟接口获取表格数据
setTimeout(()=>{
const res = {
list:[
{
key: '1',
name: '胡彦斌',
age: 32,
address: '西湖区湖底公园1号',
class:'5'
},
{
key: '2',
name: '胡彦祖',
age: 42,
address: '西湖区湖底公园1号',
class:'3'
}
],
count:2
}
setData({
count: res.count,
list:res.list
})
},200)
}
useEffect(()=>{
getList()
},[])
return(
<div>
<input
type="text"
placeholder="请输入搜索关键字"
defaultValue={paramsData.current.keyword}
onChange={ e =>{
paramsData.current.keyword = e.target.value
// 重新获取数据
getList()
}}
/>
<Table dataSource={data.list} columns={columns} />
<Modal
title="编辑班级"
visible={isModalOpen}
onOk={()=>{
// 调用接口保存编辑数据
}}
onCancel={()=>{
setodalOpen(false)
}}
>
<Select
defaultValue={itemInfo.current.class}
style={{
width: 150,
}}
options={[
{
value: '1',
label: '七年级1班',
},
{
value: '2',
label: '七年级2班',
},
{
value: '3',
label: '七年级3班',
},
{
value: '4',
label: '八年级1班',
},
{
value: '5',
label: '八年级2班',
},
{
value: '6',
label: '九年级1班',
},
]}
/>
</Modal>
</div>
)
}
若是给modal添加属性destroyOnClose
,在关闭弹框时销毁组件,在打开弹框时重新渲染,则每次都会显示正确的默认值。
111
import { useRef, useState, useEffect } from "react"
export default function UseDefaultValue (){
const paramsData = useRef({
keyword:'',
page:1,
size:10
})
const [data,setData] = useState({})
function getList(type){
setTimeout(()=>{
console.log('params',paramsData.current)
setData({
count: 1,
list:[{name:'chaochao'}]
})
if(type){
paramsData.current.keyword = '11111'
}
},200)
}
useEffect(()=>{
getList('first')
},[])
return(
<div>
<input
type="text"
defaultValue={paramsData.current.keyword}
placeholder='请输入搜索关键字'
onChange={e=>{
paramsData.current.keyword = e.target.value
getList()
}
} />
</div>
)
}
- 上述代码运行:在200ms之后窗口值变为222并且重新发送请求获取数据
- 原因:在 setData 时会 更新组件,因此 input标签会重新赋默认值为11111
何时使用defaultValue属性与value属性?
- 若是想进行
初始化赋值
就使用defaultValue属性
; - 若是
想输入的内容反馈到输入框
,就要用onChange
事件改变状态属性的 value 属性值
;