reac笔记_13 form表单元素中 input/defaultValue + useState/useRef

原生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
    
    其实本质就是
    inputele.value = '111'
    
    赋值之后就和原来的 inputvalue属性不存在关联关系了,相当于赋了一个默认值,因此 -> 修改inputvalue属性值不会影响元素的value属性,修改value属性也不会影响inputvalue属性值。

react中

在react中也不存在双向绑定!每次更新页面和值都需要我们自己去调用指定的api来触发。

受控组件与非受控组件

react中form表单元素分为受控组件与非受控组件
在这里插入图片描述

属性

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属性
  • 修正
    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,值发生改变时不会更新组件!
      在这里插入图片描述
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 属性值
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值