转载请注明出处,未经同意,不可修改文章内容。
🔥🔥🔥“前端一万小时”两大明星专栏——“从零基础到轻松就业”、“前端面试刷题”,已于本月大改版,合二为一,干货满满,欢迎点击公众号菜单栏各模块了解。
涉及面试题:
1. HTML 和 React 事件处理有什么区别?
2. 如何在 JSX 回调中绑定方法或事件处理程序?
3. 如何将参数传递给事件处理程序或回调函数?
4. React 中的合成事件是什么?
5. 每次组件渲染时调用函数的常见错误是什么?
6. 为什么有组件名称要首字母大写?
7. 在 React 中事件有何不同?
8. constructor 和 getInitialState 有什么区别?
9. 在使用 ES6 类的 React 中 super() 和 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️⃣-③:我们以上并没有进行 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;
❓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;
看下效果:
祝好,qdywxs ♥ you!