React受控组件与非受控组件详细介绍

目录
  • 1. 受控组件
    • 1.1 介绍
    • 1.2 受控组件简写
    • 1.3 在表单中使用受控组件
    • 1.4 综合案例
  • 2. 非受控组件介绍
    • 非受控组件的应用

1. 受控组件

1.1 介绍

概述:

将 state 与表单项中的 value 值绑定在一起,有 state 的值来控制表单元素的值,称为受控组件。

绑定步骤:

  • 在state中添加一个状态,作为表单元素的value值
  • 给表单元素绑定 change 事件,将表单元素的值设置为 state 的值

语法:

# value={this.state.xx} 事件onChange=“方法,修改state中的数据”
<input type="text" value={this.state.username} onChange={this.inputChange.bind(this)} />
注:多表单元素需优化事件方法
this.setState({
    [e.target.name]: e.target.value
})

使用:

import React, { Component } from 'react';
class App extends Component {
  state = {
    username: '',
    password: ''
  }
  setValue = name => evt => {
    this.setState({
      // 变量的值当前对象的key,写法
      [name]: evt.target.value.trim()
    })
  }
  login = () => {
    console.log(this.state);
  }
  render() {
    let { username, password } = this.state
    return (
      <div>
        <div>
          {/*
            表单项中的value值,通过state中的属性值来赋值的,叫受控组件
            受控组件: value={this.state.xx} 事件onChange=“方法,修改state中的数据”
          */}
          <input type="text" value={username} onChange={this.setValue('username')} />
        </div>
        <div>
          <input type="text" value={password} onChange={this.setValue('password')} />
        </div>
        <div>
          <button onClick={this.login}>登录一下</button>
        </div>
      </div>
    );
  }
}
export default App;

1.2 受控组件简写

同样是实现上面案例中的场景,我们还可以有简写方式。

loginForm.js:

export default _this => ({
  username: {
    value: '',
    onChange: e => _this.setState(state => ({ username: { ...state.username, value: e.target.value } }))
  },
  password: {
    value: '',
    onChange: e => _this.setState(state => ({ password: { ...state.password, value: e.target.value } }))
  }
})

App.jsx:

import React, { Component } from 'react';
import loginForm from './form/loginForm';
class App extends Component {
  state = {
    ...loginForm(this),
    num: 100
  }
  login = () => {
    console.log(this.state);
  }
  render() {
    let { username, password } = this.state
    return (
      <div>
        <div>
          {/* 相当于 value={username} onChange={this.setValue('username')} */}
          <input type="text" {...username} />
        </div>
        <div>
          <input type="text" {...password} />
        </div>
        <div>
          <button onClick={this.login}>登录一下</button>
        </div>
      </div>
    );
  }
}
export default App;

1.3 在表单中使用受控组件

import React, { Component } from 'react';
class App extends Component {
  state = {
    username: '',
    sex: '女',
    isshow: true,
    lessons: ['html', 'js']
  }
  setLessonsFn = e => {
    if (e.target.checked) {
      this.setState(state => ({
        lessons: [...state.lessons, e.target.value]
      }))
    } else {
      this.setState(state => ({
        lessons: state.lessons.filter(item => item != e.target.value)
      }))
    }
  }
  login = () => {
    console.log(this.state);
  }
  render() {
    let { username, sex, isshow,lessons } = this.state
    return (
      <div>
        <div>
          <input type="text" value={username} onChange={e => this.setState({ username: e.target.value })} />
        </div>
        <div>
          {/* 单选 */}
          <input type="radio" name='sex' checked={sex === '男'} value='男' onChange={e => this.setState({ sex: e.target.value })} />男
          <input type="radio" name='sex' checked={sex === '女'} value='女' onChange={e => this.setState({ sex: e.target.value })} />女
        </div>
        <div>
          {/* 单个复选框 */}
          <input type="checkbox" checked={isshow} onChange={e => this.setState({ isshow: e.target.checked })} /> 显示与隐藏
        </div>
        <div>
          {/* 多个复选框 */}
          <div>
            <input type="checkbox" value='html' checked={lessons.includes('html')} onChange={this.setLessonsFn} />html
            <input type="checkbox" value='css' checked={lessons.includes('css')} onChange={this.setLessonsFn} />css
            <input type="checkbox" value='js' checked={lessons.includes('js')} onChange={this.setLessonsFn} />js
          </div>
        </div>
        <div>
          <button onClick={this.login}>登录一下</button>
        </div>
      </div>
    );
  }
}
export default App;

1.4 综合案例

全选与反选,显示与隐藏的应用

描述:

本案例中我们将要实现,对用户名和密码进行正则验证(账号只能是邮箱或手机号,别的不行;密码必须是3位以上且有数字和字母 ),验证成功后点击登录下方显示用户列表。用户列表有删除功能,有全选和取消全选功能。选中所有的子项,全选就自动勾选,有一个子项没选中,全选就取消勾选 。

实现:

App.jsx:

import React, { Component } from 'react';
import UserTable from './components/UserTable';
class App extends Component {
  state = {
    username: '',
    password: '',
    show: false,
  }
  // 通过onChange事件来修改state中对应属性变化
  setUsername = evt => {
    // console.log(evt.target.value.trim());
    this.setState({
      username: evt.target.value.trim()
    })
  }
  setPassword = evt => {
    this.setState({
      password: evt.target.value.trim()
    })
  }
  setValue = name => evt => {
    this.setState({
      // 变量的值当前对象的key,写法
      [name]: evt.target.value.trim()
    })
  }
  submit = () => {
    if (this.regExpValue(this.state.username, "username") && this.regExpValue(this.state.password, "password")) {
      alert("登录成功!")
      this.login()
    } else {
      alert("正则验证失败,请重新输入!")
    }
  }
  regExpValue = (value, key) => {
    if (key === "username") {
      return /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/.test(value) || /^1[3-9][0-9]{9}$/.test(value);
    } else {
      return /(?=.*?[A-Za-z])(?=.*?[0-9]).{3,}/.test(value);
    }
  }
  login = () => {
    // this.setState.show=true
    this.setState({ show: true });
    console.log(this.state.show);
  }
  render() {
    let { username, password, show } = this.state
    return (
      <div>
        <div>
          {/*
            表单项中的value值,通过state中的属性值来赋值的,叫受控组件
            受控组件: value={this.state.xx} 事件onChange=“方法,修改state中的数据”
          */}
          <input type="text" value={username} onChange={this.setValue('username')} />
        </div>
        <div>
          <input type="text" value={password} onChange={this.setValue('password')} />
        </div>
        <div>

          <button onClick={this.submit}>登录一下</button>
        </div>
        {
          this.state.show
            ?
            <UserTable />
            :
            <div>不显示</div>
        }
      </div>
    );
  }
}
export default App;

UserTable.jsx:

import { getElementError } from '@testing-library/react';
import React, { Component } from 'react';
class UserTable extends Component {
  state = {
    users: [
      { id: 1, name: '张三' },
      { id: 2, name: '李四' },
      { id: 3, name: '王五' },
      { id: 4, name: '赵六' },
    ],
    isshow: true,
    uids: [],
    tip: '全选',
  }
  all = e => {
    e.target.checked
      ?
      this.setState(state => ({
        uids: state.users.map(({ id }) => id),
        tip: '取消全选'
      }))
      :
      this.setState({ uids: [], tip: '全选' })
    console.log(this.state.uids);
  }
  select = tid => e => {
    let all = document.querySelector(".all");
    if (e.target.checked) {
      setTimeout(() => {
        this.setState(state => ({
          uids: [...state.uids, tid]
        }))
        if (this.state.uids.length === 4) all.checked = true
      }, 0);
    } else {
      setTimeout(() => {
        this.setState(state => ({
          uids: state.uids.filter(item => item != tid)
        }))
        all.checked = false
        console.log(this.state.uids);
      }, 0);
    }
  }
  del = tid => () => {
    this.setState(state => ({
      users: state.users.filter(({ id }) => id !== tid)
    }))
  }
  render() {
    let { users, uids, tip } = this.state
    return (
      <div>
        <input type="checkbox" onChange={this.all} className="all" />{tip}
        <hr />
        <ul>
          {
            users.map(({ id, name }) => (
              <li key={id}>
                <span>
                  <input type="checkbox" checked={uids.includes(id)} onChange={this.select(id)} />
                </span>
                <span>{name} -- {id}</span>
                <span onClick={this.del(id)}>删除</span>
              </li>
            ))
          }
        </ul>
      </div>
    );
  }
}
export default UserTable;

2. 非受控组件介绍

概述:

表单项中的 value 或 checked 值,它不受 state 中的属性控制,但是可以而是借助 ref,通过 dom 对象来获取当前表单项中的 value 或 checked 值,这就是非受控组件。

非受控组件的应用的次数没有受控组件多,在工作中,多数使用为受控组件。

注意:react 中如何来获取普通的 html 元素的 dom 对象:ref 对象来获取。

使用步骤:

  1. 调用 React.createRef() 方法创建ref对象
  2. 将创建好的 ref 对象添加到文本框中
  3. 通过ref对象获取到文本框的值

语法:

class App extends React.Component {
  constructor(props){
    super(props)
    //创建 ref
    this.username = React.createRef()
  }
  // 获取文本框的值
  fn =() => {
    console.log(this.username.current.value)
  }
  render(){
    return (
        <div>
          <input type ="text" ref={this.username} />
          <button onClick ={this.fn}>获取值</button>
        </div>
    )
  }
}

示例:

// createRef 通过此方法得到一个ref实例对象
// ref 如果绑定在普通的html元素中则返回dom对象
// ref 如果绑定在"类组件"中,则返回当前自定义类组件实例对象,可以用它来完成组件通信
import React, { Component, createRef } from 'react'
class App extends Component {
  // 创建得到一个ref实例对象
  usernameRef = createRef()
  getUsernameInput = () => {
    // 通过ref绑定好的对象,来完成对应表单项数据的获取
    console.log(this.usernameRef.current.value)
  }
  render() {
    return (
      <div>
        <input type="text" ref={this.usernameRef} />
        <button onClick={this.getUsernameInput}>获取表单项中的数据</button>
      </div>
    )
  }
}
export default App

注意:

  1. createRef:通过此方法可以得到一个 ref 实例对象
  2. ref 如果绑定在普通的html元素中则返回dom对象
  3. ref 如果绑定在"类组件"中,则返回当前自定义类组件实例对象,可以用它来完成组件通信

非受控组件的应用

import React, { Component, createRef } from 'react'
class App extends Component {
  // 创建得到一个ref实例对象
  usernameRef = createRef()
  isShowRef = createRef()
  // 等同于:lessonsRefs = [createRef(), createRef(), createRef()]
  lessonsRefs = Array(3)
    .fill('')
    .map(_ => createRef())
  getUsernameInput = evt => {
    // 通过dom向上查找,不推荐,层级不确定,有时候会找不到
    // console.dir(evt.target.previousSibling.value)
    // 通过ref绑定好的对象,来完成对应表单项数据的获取
    console.log(this.usernameRef.current.value)
    if (this.isShowRef.current.checked) {
      console.log(this.isShowRef.current.value)
    }
    console.log(
      this.lessonsRefs
        .map(item => {
          if (item.current.checked) {
            return item.current.value
          } else {
            return null
          }
        })
        .filter(item => item != null)
    )
  }
  render() {
    return (
      <div>
        <input type="text" ref={this.usernameRef} />
        <br />
        <input type="checkbox" value="aaa" ref={this.isShowRef} />aaa
        <br />
        <input type="checkbox" value="html" ref={this.lessonsRefs[0]} />html
        <input type="checkbox" value="css" ref={this.lessonsRefs[1]} />css
        <input type="checkbox" value="js" ref={this.lessonsRefs[2]} />js
        <button onClick={this.getUsernameInput}>获取表单项中的数据</button>
      </div>
    )
  }
}
export default App

注意:

获取表单数据可以有两种方案

通过 dom 向上查找,这种方案不推荐,因为 dom 层级不确定,有时候会找不到数据

console.dir(evt.target.previousSibling.value)

通过ref绑定好的对象,来完成对应表单项数据的获取\

console.log(this.usernameRef.current.value)

到此这篇关于React受控组件与非受控组件详细介绍的文章就介绍到这了,更多相关React受控组件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 浅谈React深度编程之受控组件与非受控组件

    受控组件与非受控组件在官网与国内网上的资料都不多,有些人觉得它可有可不有,也不在意.这恰恰显示React的威力,满足不同规模大小的工程需求.譬如你只是做ListView这样简单的数据显示,将数据拍出来,那么for循坏与 {} 就足够了,但后台系统存在大量报表,不同的表单联动,缺了受控组件真的不行. 受控组件与非受控组件是React处理表单的入口.从React的思路来讲,作者肯定让数据控制一切,或者简单的理解为,页面的生成与更新得忠实地执行JSX的指令. 但是表单元素有其特殊之处,用户可以通过键盘

  • 浅谈react受控组件与非受控组件(小结)

    我们都知道,有许多的web组件可以被用户的交互发生改变,比如:<input>,<select>,或者是我现在正在使用的富文本编辑器.这些组件在日常的开发中很不显眼,我们可以很轻易的通过输入一些内容或者设置元素的value属性来改变组件的值.但是,因为React是单向数据流绑定的,这些组件可能会变得失控: 1.一个维护它自己state里的value值的<Input>组件无法从外部被修改: 2.一个通过props来设置value值的<Input>组件只能通过外部

  • 浅析React中的受控组件和非受控组件

    非受控组件 表单数据由DOM本身处理.即不受setState()的控制,与传统的HTML表单输入相似,input输入值即显示最新值(使用 ref从DOM获取表单值) 1.非受控组件 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body&g

  • React受控组件与非受控组件详细介绍

    目录 1. 受控组件 1.1 介绍 1.2 受控组件简写 1.3 在表单中使用受控组件 1.4 综合案例 2. 非受控组件介绍 非受控组件的应用 1. 受控组件 1.1 介绍 概述: 将 state 与表单项中的 value 值绑定在一起,有 state 的值来控制表单元素的值,称为受控组件. 绑定步骤: 在state中添加一个状态,作为表单元素的value值 给表单元素绑定 change 事件,将表单元素的值设置为 state 的值 语法: # value={this.state.xx} 事件

  • 浅谈Vue父子组件和非父子组件传值问题

    本文介绍了浅谈Vue父子组件和非父子组件传值问题,分享给大家,具体如下: 1.如何创建组件 1.新建一个组件,如:在goods文件夹下新建goodsList.vue <template> <div class='tmpl'> goodsList组件 </div> </template> <style> </style> <script> export default { data() { return{} }, creat

  • vue2.0父子组件及非父子组件之间的通信方法

    1.父组件传递数据给子组件 父组件数据如何传递给子组件呢?可以通过props属性来实现 父组件: <parent> <child :child-msg="msg"></child>//这里必须要用 - 代替驼峰 </parent> data(){ return { msg: [1,2,3] }; } 子组件通过props来接收数据: 方式1: props: ['childMsg'] 方式2 : props: { childMsg: Arr

  • Android 开发音频组件(Vitamio FAQ)详细介绍

     一.Vitamio介绍 1.1 Vitamio是什么? Vitamio是Android平台视音频播放组件,支持播放几乎格式的视频以及主流网络视频流(http/rtsp/mms等),详细的中文介绍: 这里. Vitamio官网:http://vitamio.org/ Vitamio微博:http://weibo.com/vitamio VPlayer官网:http://vplayer.net Vitamio豆瓣:http://site.douban.com/145815/ 1.2 关于Vitam

  • Vue 中的受控与非受控组件的实现

    受控组件 什么是受控组件? 其值由React控制的输入表单元素称为"受控组件". 受控组件有两个特点:1. 设置value值,value由state控制,2. value值一般在onChange事件中通过setState进行修改 什么时候使用受控组件? 需要对组件的value值进行修改时,使用受控组件.比如:页面中有一个按钮,每点击一次按钮受控组件的值加1. 非受控组件 什么是非受控组件? 表单数据由 DOM 处理的组件非受控组件. 非受控组件有两个特点:1. 不设置value值,2.

  • 从零搭建react+ts组件库(封装antd)的详细过程

    目录 整体需求 开发与打包工具选型 使用webpack作为打包工具 使用babel来处理typescript代码 使用less-loader.css-loader等处理样式代码 项目搭建思路 整体结构 方案思路 项目搭建实施 初始化 Babel引入 了解Babel webpack的基于babel-loader的处理流程 引入React相关库(externals方式) 编写组件代码 编译打包组件库 效果演示 处理样式(less编译与css导出) 依赖引入 配置webpack 编写样式代码 编译组件

  • React路由渲染方式与withRouter高阶组件及自定义导航组件应用详细介绍

    目录 1. 路由的三种渲染方式 1.1 component渲染方式 1.2 render方式渲染 1.3 案例-登录成功才能访问某个页面 1.4 children方式渲染 2. withRouter高阶组件 3. 自定义导航组件 1. 路由的三种渲染方式 1.1 component渲染方式 描述: 这种渲染方式有两种,一种是类方式渲染,一种是函数方式渲染. 语法: <Route path="/home" component={Home} /> 或 <Route pat

随机推荐