React --- 组件的三大属性state、props、refs和事件处理

目录

1.state

state是组件中最重要的一个属性,值是对象(可包含多个key-value组合)
组件被称为"状态机",通过更新组件的state来更新对应的页面显示(重新渲染组件)

注意:

①组件中render方法中的this为组件实例对象
②组件自定义的方法中的this位undefined,如何解决?
通过函数对象的bind函数强制绑定this 或者 使用箭头函数
③状态数据,需要通过setState()函数来修改,不能直接更改

小案例

实现点击切换的效果 

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"></meta>
    <title></title>
  </head>
  <body>
    <div id="test"></div>

    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>

    <script type="text/babel">
      class Weather extends React.Component {
        constructor(props) {
          super(props)
          this.state = {isHot:false}
          // 类中的方法默认开启了局部的strict模式,所以changeWeather中的this位undefined
          // 解决changeWeather中this指向的问题
          this.cWeather = this.changeWeather.bind(this)
        }
        render() {
          const {isHot} = this.state
          return <h2 onClick={this.cWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
        }
        changeWeather() {
          // 状态state不可直接修改,需要通过setState方法
          const isHot = this.state.isHot
          this.setState({isHot:!isHot})
        }
      }
      ReactDOM.render(<Weather/>, document.getElementById('test'))
    </script>
  </body>
</html>

简化写法(推荐)

<script type="text/babel">
  class Weather extends React.Component {
    constructor(props) {
      super(props)
    }
    state = {isHot:false}
    render() {
      const {isHot} = this.state
      return <h2 onClick={this.changeWeather}>今天天气很{isHot ? '炎热' : '凉爽'}</h2>
    }
    // 自定义方法 --- 要用赋值语句的形式 + 箭头函数(用changeWeather = function(){}不行)
    // 箭头函数下面的this,如果发现自己是undefined,就会向外层寻找,所以这里的this指向的是weather实例对象
    changeWeather = () => {
      const isHot = this.state.isHot
      this.setState({isHot:!isHot})
    }
  }
  ReactDOM.render(<Weather/>, document.getElementById('test'))
</script>

补充:原生js中绑定点击事件的三种方式

<button id="btn1">按钮1</button>
<button id="btn2">按钮2</button>
<button onclick="demo()">按钮3</button>
<script type="text/javascript">
// 第一种
const btn1 = document.getElementById('btn1')
btn1.addEventListener('click', ()=>{
   alert('按钮1被点击了')
})
// 第二种
const btn2 = document.getElementById('btn2')
btn2.onclick = ()=>{
   alert('按钮2被点击了')
}
// 第三种
function demo() {
   alert('按钮3被点击了')
}
</script>

2.props

React组件中的props主要是用来接收传入的数据的 

小案例 

需求:自定义一个用来显示个人信息的组件
           姓名必须指定,并且为字符串类型
           性别为字符串类型,没有指定就默认为男
           年龄为数字类型,默认值为18 

prop-types.js下载地址https://unpkg.com/prop-types@15.6.2/prop-types.js

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8"></meta>
    <title>Document</title>
  </head>
  <body>
    <div id="test1"></div>
    <div id="test2"></div>

    <script type="text/javascript" src="../js/react.development.js"></script>
    <script type="text/javascript" src="../js/react-dom.development.js"></script>
    <script type="text/javascript" src="../js/babel.min.js"></script>
    <!-- 引入prop-types,全局就多了一个propTypes对象,用于对组件标签属性进行限制 -->
    <script type="text/javascript" src="../js/prop-types.js"></script>

    <script type="text/babel">
      class Person extends React.Component {
        render() {
          const {name,age,sex,speak} = this.props
          return (
            <ul>
              <li>姓名:{name}</li>
              <li>性别:{sex}</li>
              <li>年龄:{age}</li>
            </ul>
          )
        }
      }
      // 对标签属性进行类型、必要性的限制
      Person.propTypes = {
        name: PropTypes.string.isRequired,
        sex: PropTypes.string,
        age: PropTypes.number,
        speak: PropTypes.func
      }
      // 指定默认标签属性值
      Person.defaultProps = {
        sex: '男',
        age: 18
      }
      const p1 = {name: 'Tom', age:18, sex: '男', speak: speak}
      const p2 = {name: 'Nancy', age:19, sex: '女'}
      function speak() {
        console.log('我说话了')
      }
      ReactDOM.render(<Person {...p1}/>, document.getElementById('test1'))
      ReactDOM.render(<Person {...p2}/>, document.getElementById('test2'))
    </script>
  </body>
</html>

也可以把标签属性的限制放在类里面(推荐)

class Person extends React.Component {
   static propTypes = {
      name: PropTypes.string.isRequired,
      sex: PropTypes.string,
      age: PropTypes.number,
      speak: PropTypes.func
    }
    static defaultProps = {
      sex: '男',
      age: 18
    }
    render() {
      const {name,age,sex,speak} = this.props
       return (
         <ul>
           <li>姓名:{name}</li>
           <li>性别:{sex}</li>
           <li>年龄:{age}</li>
         </ul>
       )
    }
}

上面的都是用类式组件写的,下面我们用函数式组件写一下

// 其它代码同上
<script type="text/babel">
  function Person (props) {
    const {name,age,sex} = props
    return (
      <ul>
        <li>姓名:{name}</li>
        <li>性别:{sex}</li>
        <li>年龄:{age}</li>
      </ul>
    )
  }
  Person.propTypes = {
    name: PropTypes.string.isRequired,
    sex: PropTypes.string,
    age: PropTypes.number,
    speak: PropTypes.func
  }
  Person.defaultProps = {
    sex: '男',
    age: 18
  }

  const p1 = {name: 'Tom', age:18, sex: '男'}
  const p2 = {name: 'Nancy', age:19, sex: '女'}   
  ReactDOM.render(<Person {...p1}/>, document.getElementById('test1'))   
  ReactDOM.render(<Person {...p2}/>, document.getElementById('test2'))
</script>

3.refs

组件中的标签可以用refs来标识自己,类似于id,但用法不同

小案例 

点击按钮,显示输入框的数据
失去焦点,显示输入框的数据 

①String 类型的 Refs (效率低,官方不推荐使用了)

// 其它代码同上
<script type="text/babel">
  class Demo extends React.Component {
    showData = () => {
      const {input1} = this.refs
      alert(input1.value)
    }
    showData2 = () => {
      const {input2} = this.refs
      alert(input2.value)
    }
    render() {
      return (
        <div>
          <input ref="input1" type="text" placeholder="点击按钮提示数据" />&nbsp;
          <button onClick={this.showData}>点我提示左侧的数据</button><br/>
          <input ref="input2" onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
        </div>
      )
    }
  }
  ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>

 ②回调函数形式的 Refs

// 其它代码同上
<script type="text/babel">
  class Demo extends React.Component {
    showData = () => {
      const {input1} = this
      alert(input1.value)
    }
    showData2 = () => {
      const {input2} = this
      alert(input2.value)
    }
    render() {
      return (
        <div>
          <input ref={c => this.input1 = c} type="text" placeholder="点击按钮提示数据" />&nbsp;
          <button onClick={this.showData}>点我提示左侧的数据</button><br/>
          <input ref={c => this.input2 = c} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
        </div>
      )
    }
  }
  ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>

上面的 ref 回调函数是以内联函数的方式定义的,在更新过程中它会被执行两次,第一次传入参数 null,然后第二次会传入参数 DOM 元素。想要避免,用类绑定的形式,看下面。

// 其它代码同上
<script type="text/babel">
  class Demo extends React.Component {
    showData = () => {
      const {input1} = this
      alert(input1.value)
    }
    showData2 = () => {
      const {input2} = this
      alert(input2.value)
    }
    assignment1 = c => { this.input1 = c;}
    assignment2 = c => { this.input2 = c;}
    render() {
      return (
        <div>
         <input ref={this.assignment1} type="text" placeholder="点击按钮提示数据" />&nbsp;
         <button onClick={this.showData}>点我提示左侧的数据</button><br/>
         <input ref={this.assignment2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
        </div>
      )
    }
  }
  ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>

③ 用React.createRef() 返回的容器存储refs标识的结点(推荐)

// 其它代码同上
<script type="text/babel">
  class Demo extends React.Component {
    // React.createRef()调用后返回一个容器,该容器可以存储被ref标识的结点,一个容器装一个结点
    myRef = React.createRef()
    myRef2 = React.createRef()
    showData = () => {
      alert(this.myRef.current.value)
    }
    showData2 = () => {
      alert(this.myRef2.current.value)
    }
    render() {
      return (
        <div>
          <input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />&nbsp;
          <button onClick={this.showData}>点我提示左侧的数据</button><br/>
          <input ref={this.myRef2} onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
        </div>
      )
    }
  }
  ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>

4.事件处理 

通过onXxx属性指定时间处理函数(注意大小写)

React使用的是自定义(合成)事件,而不是使用原生DOM事件
React中的事件是通过事件委托方式处理的(委托给组件最外层的元素)

通过event.target得到发生事件的DOM元素对象
我们把上面的例子改一下,官方文档告诉我们不要过多使用refs,当发生事件的元素和事件操作的元素是同一个时,我们可以省略标签的ref,用event.target获取该元素

// 其它代码同上
<script type="text/babel">
  class Demo extends React.Component {
    myRef = React.createRef()
    myRef2 = React.createRef()
    showData = () => {
      alert(this.myRef.current.value)
    }
    showData2 = (event) => {
      alert(event.target.value)
    }
    render() {
      return (
        <div>
          <input ref={this.myRef} type="text" placeholder="点击按钮提示数据" />&nbsp;
          <button onClick={this.showData}>点我提示左侧的数据</button><br/>
          <input onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
        </div>
      )
    }
  }
  ReactDOM.render(<Demo/>, document.getElementById('test'))
</script>
  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
回答: React中的三大属性propsstaterefs。\[1\] props组件属性,可以通过this.props来访问。它可以用来传递数据给组件,并且可以对属性值进行类型限制和必要性限制。可以使用PropTypes来进行属性类型的限制,也可以设置默认属性值。\[1\] state组件的状态,可以通过this.state来访问。它用于存储组件内部的数据,并且可以通过setState方法来更新状态。状态的改变会触发组件的重新渲染。\[2\] refs是用来标识组件内部标签的引用。它可以通过字符串形式或者React.createRef()来定义。通过refs可以获取到标签的真实DOM节点或者组件实例。\[3\] 这三大属性React中非常重要,可以帮助我们管理组件的数据和交互。 #### 引用[.reference_title] - *1* [react三大属性](https://blog.csdn.net/weixin_30617797/article/details/102410491)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [React —— React组件三大属性state,props,ref)](https://blog.csdn.net/Bonsoir777/article/details/127568414)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

漂流の少年

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值