react学习——受控组件及非受控组件及ref获取dom节点

本文介绍了React中创建项目的两种方式,重点讲解了受控组件和非受控组件的概念与用法。受控组件通过事件处理函数更新state,保持数据的一致性;而非受控组件则允许DOM元素直接管理其状态。文中还讨论了如何使用ref获取DOM节点,以及在处理文件输入时非受控组件的应用。
摘要由CSDN通过智能技术生成

react 创建项目的两种方式

  • 1.npm 全局安装
npm install -g create-react-app
create-react-app my-react-app

一般安装到了你的npm文件夹下
设置在系统的环境变量里面

  • 2.npx 非全局安装
// 现将 my-react-app下载到本地,用完删除
npx create-react-app my-react-app

受控表单(受控组件)

什么是表单??

  • 在React里,HTML表单元素的工作方式和其他的DOM元素有些不同,这是因为表单元素会保持一些内部的state.
  • 例如这个纯 HTML 表单只接受一个名称:
<form>
  <label>
    名字:
    <input type="text" name="name" />
  </label>
  <input type="submit" value="提交" />
</form>
  • 此表单具有默认的 HTML 表单行为,即在用户提交表单后浏览到新页面。
  • 如果你在 React 中执行相同的代码,它依然有效。
  • 但大多数情况下,使用 JavaScript 函数可以很方便的处理表单的提交, 同时还可以访问用户填写的表单数据。实现这种效果的标准方式是使用“受控组件”

什么是受控组件?

  • 在 HTML 中,表单元素(如<input><textarea><select>)通常自己维护 state,并根据用户输入进行更新。
  • 而在 React 中,可变状态(mutable state)通常保存在组件的 state 属性中,并且只能通过使用setState()来更新。

input受控:

例1:如果我们想让前一个示例在提交时打印出名称

  • 我们可以将表单写为受控组件:
import React, { Component } from 'react'
// 如何获取表单数据?????
// 获取值/存值

// 受控表单
// 可以设置默认值
// defaultValue 
export default class App extends Component {
  state={
    username:"",
  }
  handleClick=(params) => {
    // console.log(this.username);
    console.log(this.state.username);
  }
  handleChange=(e) => {
    // 默认传一个事件源
    // 传参之后事件源跑哪里去了?作为里面的第二个参数传入
    // 1-获取到表单中的值
    let username = e.target.value
    console.log(username);
    // 2-存值
    // 2-1.放对象里 this.username = e.target.value
    // this.username = e.target.value
    // 2-2.放状态里 this.username = e.target.value
    this.setState({
      username:e.target.value
    })
    // 为什么第二种好??
    // 输入框本来是自己控制的
    // 怎么设置成受我们控制,而不受浏览器控制
    // 受控表单有初始value时,再输入就不受浏览器控制了
    // 所以想要更新界面的话。就要使用改变状态的方式了,成为受我们控制的表单 
  }
  render() {
    return (
      <div>
        {/* 登录框的例子 */}
        <label htmlFor="username">
          用户名: <input type="text" id="username" value={this.state.username} onChange={this.handleChange}/>
        </label>
        <br></br>
        <label htmlFor="password">
          密码: <input type="password" id="password"/>
        </label>
        <br></br>
        <button onClick={this.handleClick}>提交</button>
      </div>
    )
  }
}
  • 由于在表单元素上设置了 value 属性,因此显示的值将始终为 this.state.value,这使得 React 的 state 成为唯一数据源。
  • 由于 handlechange 在每次按键时都会执行并更新 React 的 state,因此显示的值将随着用户输入而更新。
  • 对于受控组件来说,输入的值始终由 React 的 state 驱动。

例2:合并多个输入

  • 当需要处理多个input元素时,我们可以给每个元素添加name属性,并让处理函数根据event.target.name的值选择要执行的操作。
  • 下面的是使用data属性,其实原理是一样的。
  • 还想获取密码,需要在密码框中再定义一个相似的onChange事件,所以想把这两个相似的事件合并成一个事件就解决,获取不同输入框的不同的value值,
  • 这里使用了data属性,命名成了data-name
import React, { Component } from "react";
// 合并多个输入
export default class App extends Component {
  state = {
    username: "",
    password: "",
  };
  handleClick = (params) => {
    console.log(this.state.username, this.state.password);
  };
  // handleChange = (e) => {
  //   this.setState({
  //     username: e.target.value,
  //   });
  // };
  // 原来的密码框事件是叫这个handlePasswordChange
  // handlePasswordChange = (e) => {
  //   this.setState({
  //     password: e.target.value,
  //   });
  // };
  // 两个函数合并成一个
  // 传参 合并多个输入
  // e.target.dataset.name
  handleChange = (e) => {
    this.setState({
      [e.target.dataset.name]: e.target.value,
    });
  };
  render() {
    return (
      <div>
        <label htmlFor="username">
          用户名:{" "}
          <input
            type="text"
            id="username"
            data-name="username"
            value={this.state.username}
            onChange={this.handleChange}
          />
        </label>
        <br></br>
        <label htmlFor="password">
          密码:{" "}
          <input
            type="password"
            id="password"
            data-name="password"
            value={this.state.password}
            onChange={this.handleChange}
          />
        </label>
        <br></br>
        <button onClick={this.handleClick}>提交</button>
      </div>
    );
  }
}

select受控:

  • 在HTML中
<select>
  <option value="grapefruit">葡萄柚</option>
  <option value="lime">酸橙</option>
  <option selected value="coconut">椰子</option>
  <option value="mango">芒果</option>
</select>
  • 请注意,由于 selected 属性的缘故,椰子选项默认被选中。
  • React 并不会使用 selected 属性,而是在根 select 标签上使用 value 属性。这在受控组件中更便捷,因为您只需要在根标签中更新它。
  • 例如:
import React, { Component } from 'react'
// select表单
// 怎么变为 受控表单
export default class App extends Component {
  // 调用父类的初始化的方法
  constructor(props){
    super(props)
    this.state={
      selectValue:"中文",
    }
  }
  handleChange=(e) => {
    this.setState({
      selectValue:e.target.value
    })
  }
  render() {
    return (
      <div>
        <select name="" id="" value={this.state.selectValue} onChange={this.handleChange}>
          <option value="粤语">粤语</option>
          <option value="德语">德语</option>
          <option value="中文">中文</option>
        </select>
      </div>
    )
  }
}
  • 总的来说,这使得, <input type="text">, <textarea><select>之类的标签都非常相似—它们都接受一个 value 属性,你可以使用它来实现受控组件。

受控输入空值时!

非受控组件

文件 input 标签

  • 在 HTML 中,<input type="file"> 允许用户从存储设备中选择一个或多个文件,将其上传到服务器,或通过使用 JavaScript 的 File API 进行控制。
  • 因为它的 value 只读,所以它是 React 中的一个非受控组件。
<input type="file" />
  • 在react中,执行下面的代码,会报错
import React, { Component } from "react";
export default class App extends Component {
  state = {
    value:"",
  };
  componentDidMount() {
    document.getElementById("file").addEventListener("change", function (e) {
      // 获取到上传文件的内容
      console.log(e.target.files);
    });
  }
  render() {
    return (
      <div>
        <input type="file" name="" id="file" value={this.state.value} />
      </div>
    );
  }
}

  • 在这里插入图片描述
  • 非受控表单

ref获取dom节点

例子1:

import React, { Component } from "react";
export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {};
    // 1- 创建了一个 ref
    this.fileref = React.createRef();
  }
  componentDidMount() {
    document.getElementById("file").addEventListener("change", function (e) {
      // 获取到上传文件的内容
      console.log(e.target.files);
    });
  }
  handleClick = (e) => {
    console.log(this.fileref.current.value);
  };
  render() {
    return (
      <div>
        <input type="file" name="" id="file" ref={this.fileref}/>
        <button onClick={this.handleClick}>获取dom节点</button>
      </div>
    );
  }
}

例子2:输入框自动聚焦

import React, { Component } from 'react'
// 输入框自动聚焦
// 在挂载的时候,ref获取节点,给他onFous
export default class App extends Component {
  constructor(props){
    super(props)
    this.inputRef = React.createRef()
  }
  componentDidMount() {
      // document.getElementById("text").focus()
      this.inputRef.current.focus()
  }
  render() {
    return (
      <div>
        <input type="text" id="text" ref={this.inputRef}/>
      </div>
    )
  }
}
  • 因为非受控组件将真实数据储存在 DOM 节点中,所以在使用非受控组件时,有时候反而更容易同时集成 React 和非 React 代码。如果你不介意代码美观性,并且希望快速编写代码,使用非受控组件往往可以减少你的代码量。否则,你应该使用受控组件。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值