(05)React 入门——② 响应式设计思想和事件绑定 | React 基础理论实操

9,721 阅读6分钟
转载请注明出处,未经同意,不可修改文章内容。

🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。


涉及面试题:
 1. HTMLReact 事件处理有什么区别?
 2. 如何在 JSX 回调中绑定方法或事件处理程序?
 3. 如何将参数传递给事件处理程序或回调函数?
 4. React 中的合成事件是什么?
 5. 每次组件渲染时调用函数的常见错误是什么?
 6. 为什么有组件名称要首字母大写?
 7.React 中事件有何不同?
 8. constructor 和 getInitialState 有什么区别?
 9. 在使用 ES6 类的 Reactsuper() 和 super(props) 有什么区别?
10. 如何将参数传递给事件处理程序?

[编号:react_05]

1 响应式设计思想

❓需求:紧接着上篇文章的代码,假设我们想实现——在 input 框里输入内容,点击“提交”按钮后,这个内容会显示在下边的“列表”里。

答:

  • 原生 JS 的实现方式——我们会给“提交”这个按钮绑定一个事件,然后获取到 input 框里的 value 值。接着通过 document.getElementById 找到这个“列表”的外层区块,然后把 input 框里的内容“挂载”到这个外层 DOM 元素之中。即,通过操作 DOM 的形式来实现功能

  • React 的实现方式——React 是一个“响应式”的框架,它与原生 JS 直接操作 DOM 的思想完全不一样。它强调的是“React 自动感知数据的变化,然后自动地生成 DOM”。所以在写 React 代码的时候,我们不需要关注 DOM 相关的操作,只需要关注“数据层”的操作就可以了。

    • React 具体实现以上需求的步骤为:

1️⃣既然 React 编码只需考虑“数据层”的操作,那么在实现上边的需求时,我们页面上会有多少“数据”呢? 答:只需要两组“数据”就可以了——一组“数据”来存储 input 框里的“”;另一组“数据”来存储列表中的“每一项”。

打开 TodoList.js 文件,我们在代码里去定义两个数据项:

🔗前置知识:
《面向对象编程:③ “继承”和“ ES6 模块化”》
《JS 函数:⑤ 彻底弄懂各种情况下的 this 指向》

import React, { Component, Fragment } from "react"; 

class TodoList extends Component {
  
  constructor(props) {  
    super(props)  /*
    							❗️这两行代码是 ES6 语法里的“继承”固定写法。
                  参数 props 先暂时不管,后边会详讲!
                   */
    
    this.state = { // 2️⃣React 中,我们将“数据”项定义在组件的“状态 state”里;
      
      inputValue: "", /*
      								3️⃣  
      								3️⃣-①:第一个“数据”项是 input 框里的“内容”(它是一个“字符串”);
                       */
      list: [] // 3️⃣-②:通过一个“数组”来存储列表里的每一项。
    }
  }
  
  render() {
    return(

      <Fragment>
        <div>
      
      		{// 4️⃣input 框里的内容是由“组件”的 state 状态对应的“inputValue 值”决定的;
          /*
          ❗️❗️❗️在“JSX 语法”中,我们在标签中书写“JS 表达式”时,需要用 {} 括起来!
          ❗️❗️❗️哪怕是写“注释”,也一样要用 {} 括起来!
           */}
          <input value={this.state.inputValue}/>  
      
          <button>提交</button>
        </div>
        <ul>
          <li>React 初识</li>
          <li>React 入门</li>
          <li>React 进阶</li>
        </ul>
      </Fragment>
    )
  }
}

export default TodoList;

5️⃣我们可以测试一下我们说过的话“input 框里的值是由 inputValue 里的内容决定的”:

this.state = {  
  inputValue: "hello~", // 5️⃣-①:我们在“组件”的 state 状态对应的 inputValue 里写一些内容;
  list: [] 
}

5️⃣-②:返回页面查看(input 框里的值确实变成了 hello~ ):

5-1.png

❓5️⃣-③:我们以上并没有进行 DOM 的任何操作,但为什么页面可以变化呢?

答:React 的英文意思为“响应”。之所以取这个名字,是因为 React 能感受到“数据”的变化,然后自动的把数据映射到页面之上(即“数据”一变化,页面就会随之“响应”这个变化)。

❓5️⃣-④:为什么此时在页面上的 input 输入框里输入内容无效(你可以试一试,任你键盘怎么敲打,input 框里都不会有任何字符显示)?

答:同理,input 框里的内容是由“组件”的 state 状态对应的 inputValue 里面的内容决定的。我们上边把 inputValue 里的内容写死了,即永远都会是这个值,故任你再怎么在页面的 input 框怎么输入,页面都不会有任何变化。

❓5️⃣-⑤:怎样去除这个 bug,使我们能在 input 框里自由输入,且能显示出来呢?

答:给 input 框绑定一些事件!

2 React 中的事件绑定

6️⃣给 input 框绑定一些事件:

import React, { Component, Fragment } from "react"; 

class TodoList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      inputValue: "", // ❗️将这里设置为“空字符串”,以便我们自由地输入。
      list: []
    };
  }

  render() {
    return(

      <Fragment>
        <div>
      
          <input 
      			value={this.state.inputValue}
            
  					onChange={this.handleInputChange.bind(this)}
    			/>
  					{/*
             6️⃣-①:我们给 input 框绑定一个 onChange 监听事件,当输入框里的内容有变化时,
             将执行 handleInputChange 方法;
             6️⃣-②:React 里绑定事件的写法区别于原生 JS,React 里要用“驼峰”——onChange;
             6️⃣-③:同理,“JSX 语法”要求我们将“JS 表达式”用 {} 括起来;
             6️⃣-④:之所以要用 .bind(this) ,是因为要确保 this 的指向为 TodoList;
              */}

          <button>提交</button>
        </div>
        <ul>
          <li>React 初识</li>
          <li>React 入门</li>
          <li>React 进阶</li>
        </ul>
      </Fragment>
    )
  }
  
  // 6️⃣-⑤:我们在这里增加一个 handleInputChange 方法,传入一个 event 事件——onChange;
  // 6️⃣-⑥:onChange 事件有一个 target 属性,它指向 input 框对应的 DOM 节点;
  // 6️⃣-⑦:而该 DOM 节点有对应的 value 值。此时,我们可以在页面的 input 框再输入试试;
  handleInputChange(e) {
    console.log(e.target.value)
  }

}

export default TodoList;

5-2.gif

❓6️⃣-⑧:从上图看,事件绑定倒是生效了,控制台也打印出了我们的“输入”,但是页面上依然没什么变化啊!怎么解决?

答:一样的道理——input 框里的内容是由“组件”的 state 状态对应的 inputValue 里面的内容决定的。你想改变显示的内容,那么就要改变 inputValue

7️⃣React 给每个组件提供了一个方法 setState() 。如果你想改变“组件”的 state 状态里的“数据项”,你必须调用这个方法:

import React, { Component, Fragment } from "react"; 

class TodoList extends Component {
  constructor(props) {
    super(props);

    this.state = {
      inputValue: "", 
      list: []
    };
  }

  render() {
    return(

      <Fragment>
        <div>
      
          <input 
            value={this.state.inputValue}
            onChange={this.handleInputChange.bind(this)}
          />

          <button>提交</button>
        </div>
        <ul>
          <li>React 初识</li>
          <li>React 入门</li>
          <li>React 进阶</li>
        </ul>
      </Fragment>
    )
  }

  handleInputChange(e) {
    // console.log(e.target.value)
    this.setState({
      inputValue: e.target.value /*
      													 🚀我们需要改变 inputValue 这个数据项,
                                 使其内容为 e.target.value。
                                  */
    })
  }
}

export default TodoList;

看下效果: 5-3.gif

祝好,qdywxs ♥ you!