React基本内容学习详细教程(3)

一时失言乱红尘 2023-10-12 09:51 114阅读 0赞

上篇续写

React基本内容学习详细教程(1)
React基本内容学习详细教程(2)

详细内容

1)React 组件生命周期

组件的生命周期可分成三个状态:

  • Mounting(挂载):已插入真实 DOM
  • Updating(更新):正在被重新渲染
  • Unmounting(卸载):已移出真实 DOM
    在这里插入图片描述

挂载

当组件实例被创建并插入 DOM 中时,其生命周期调用顺序如下:

constructor():在 React 组件挂载之前,会调用它的构造函数。
getDerivedStateFromProps():在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。
render():render() 方法是 class 组件中唯一必须实现的方法。
componentDidMount():在组件挂载后(插入 DOM 树中)立即调用。
render() 方法是 class 组件中唯一必须实现的方法,其他方法可以根据自己的需要来实现。

更新

每当组件的stateprops发生变化时,组件就会更新。

当组件的 props 或 state 发生变化时会触发更新。组件更新的生命周期调用顺序如下:

getDerivedStateFromProps(): 在调用 render 方法之前调用,并且在初始挂载及后续更新时都会被调用。根据 shouldComponentUpdate() 的返回值,判断 React 组件的输出是否受当前 state 或 props 更改的影响。
shouldComponentUpdate():当 props 或 state 发生变化时,shouldComponentUpdate()会在渲染执行之前被调用。
render():render() 方法是 class 组件中唯一必须实现的方法。
getSnapshotBeforeUpdate(): 在最近一次渲染输出(提交到 DOM 节点)之前调用。
componentDidUpdate():在更新后会被立即调用。
render() 方法class 组件中唯一必须实现的方法,其他方法可以根据自己的需要来实现。

卸载

当组件从 DOM 中移除时会调用如下方法:

componentWillUnmount():在组件卸载及销毁之前直接调用

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. class Clock extends React.Component {
  4. constructor(props) {
  5. super(props);
  6. // 初始化组件状态,包含一个名为date的属性,值为当前时间的Date对象
  7. this.state = {
  8. date: new Date() };
  9. }
  10. // 组件挂载完成后调用的生命周期方法
  11. componentDidMount() {
  12. // 使用定时器每秒更新一次组件状态中的date属性
  13. this.timerID = setInterval(() => this.tick(), 1000);
  14. }
  15. // 组件卸载前调用的生命周期方法
  16. componentWillUnmount() {
  17. // 清除定时器
  18. clearInterval(this.timerID);
  19. }
  20. // 更新组件状态的方法
  21. tick() {
  22. // 更新date属性为当前时间的Date对象
  23. this.setState({
  24. date: new Date()
  25. });
  26. }
  27. render() {
  28. return (
  29. <div>
  30. {
  31. /* 显示标题 */}
  32. <h1>Hello, react!</h1>
  33. {
  34. /* 显示当前时间 */}
  35. <h2>现在时间是:{
  36. this.state.date.toLocaleTimeString()}.</h2>
  37. </div>
  38. );
  39. }
  40. }
  41. // 将Clock组件渲染到id为"example"的DOM元素中
  42. ReactDOM.render(
  43. <Clock />,
  44. document.getElementById('example')
  45. );
  • Clock的类组件。在构造函数中,初始化了组件的状态date,值为当前时间的Date对象。
  • componentDidMount生命周期方法中,使用定时器每秒更新一次组件状态的date属性
  • componentWillUnmount生命周期方法中,清除定时器,以防止在组件卸载后仍然执行更新。
  • tick方法用于更新组件状态中的date属性为当前时间的Date对象
  • 在render方法中,通过JSX语法,将标题和显示当前时间的元素渲染到DOM中
  • {this.state.date.toLocaleTimeString()}用于显示当前时间的格式化字符串。
  • 最后,通过ReactDOM.renderClock组件渲染到id为"example"的DOM元素中。
    在这里插入图片描述

2)React AJAX

React 组件的数据可以通过 componentDidMount方法中的 Ajax来获取,当从服务端获取数据时可以将数据存储在 state 中,再用 this.setState 方法重新渲染 UI

当使用异步加载数据时,在组件卸载前使用componentWillUnmount 来取消未完成的请求。

3)React 表单与事件

  • HTML 表单元素与 React 中的其他 DOM 元素有所不同,因为表单元素生来就保留一些内部状态。
  • 在 HTML 当中,像 , , 和 这类表单元素会维持自身状态,并根据用户输入进行更新。
  • 但在React中,可变的状态通常保存在组件的状态属性中,并且只能用 setState() 方法进行更新

    import React from ‘react’;
    import ReactDOM from ‘react-dom’;

    class Message extends React.Component {

    1. constructor(props) {
    2. super(props);
    3. // 初始化组件状态
    4. this.state = {
    5. value: 'hello,world'
    6. };
    7. // 绑定change方法的上下文
    8. this.change = this.change.bind(this);
    9. }
    10. // 当输入框的值发生变化时触发
    11. change(event) {
    12. // 更新组件状态,将输入框的值存储在state中
    13. this.setState({
    14. value: event.target.value });
    15. }
    16. render() {
    17. // 从state中获取当前的值
    18. var value = this.state.value;
    19. return (
    20. <div>
    21. {
    22. /* 输入框,value绑定为state中的值,onChange事件触发change方法 */}
    23. <input type="text" value={
    24. value} onChange={
    25. this.change} />
    26. {
    27. /* 显示state中的值 */}
    28. <h1>{
    29. value}</h1>
    30. </div>
    31. );
    32. }

    }

    ReactDOM.render(

    1. <Message />,
    2. document.getElementById('example')

    );

在这里插入图片描述

  • 如何在子组件上使用表单onChange方法将触发 state 的更新并将更新的值传递到子组件的输入框的 value 上来重新渲染界面
  • 你需要在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp) 传递到你的子组件上。

    import React from ‘react’;
    import ReactDOM from ‘react-dom’;

    // Content组件
    class Content extends React.Component {

    1. render() {
    2. return (
    3. <div>
    4. {
    5. /* 输入框,value绑定为传入的myDataProp值,onChange事件绑定为传入的updateStateProp方法 */}
    6. <input type="text" value={
    7. this.props.myDataProp} onChange={
    8. this.props.updateStateProp} />
    9. {
    10. /* 显示传入的myDataProp值 */}
    11. <h4>{
    12. this.props.myDataProp}</h4>
    13. </div>
    14. );
    15. }

    }

    // HelloMessage组件
    class HelloMessage extends React.Component {

    1. constructor(props) {
    2. super(props);
    3. // 初始化组件状态
    4. this.state = {
    5. value: '你好,Java!'
    6. };
    7. // 绑定handleChange方法的上下文
    8. this.handleChange = this.handleChange.bind(this);
    9. }
    10. // 当输入框的值发生变化时触发
    11. handleChange(event) {
    12. // 更新组件状态,将输入框的值存储在state中
    13. this.setState({
    14. value: event.target.value });
    15. }
    16. render() {
    17. var value = this.state.value;
    18. return (
    19. <div>
    20. {
    21. /* 渲染Content组件,传入value作为myDataProp,传入handleChange方法作为updateStateProp */}
    22. <Content myDataProp={
    23. value} updateStateProp={
    24. this.handleChange} />
    25. </div>
    26. );
    27. }

    }

    // 将HelloMessage组件渲染到id为”example”的DOM元素中
    ReactDOM.render(

    1. <HelloMessage />,
    2. document.getElementById('example')

    );

  • 代码中有两个组件:ContentHelloMessage

  • Content组件包含一个输入框一个标题,根据myDataProp的值来设置输入框的值,并显示在标题中。
  • HelloMessage组件包含一个状态value,初始化为"你好,Java!"。它也有一个handleChange方法,用于更新状态value的值
  • 在HelloMessage组件的render方法中,通过标签将Content组件渲染到DOM中,传递了value作为myDataProp的值,并将handleChange方法作为updateStateProp传递给Content组件
  • 最后,通过ReactDOM.renderHelloMessage组件渲染到id"example"的DOM元素中。
    在这里插入图片描述

Select 下拉菜单

在 React 中,不使用 selected 属性,而在根 select 标签上用 value 属性来表示选中项。
在这里插入图片描述

多个表单

当你有处理多个 input 元素时,你可以通过给每个元素添加一个 name 属性,来让处理函数根据 event.target.name 的值来选择做什么

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. class FlavorForm extends React.Component {
  4. constructor(props) {
  5. super(props);
  6. // 初始化组件状态
  7. this.state = {
  8. value: 'coconut'
  9. };
  10. // 绑定方法的上下文
  11. this.handleChange = this.handleChange.bind(this);
  12. this.handleSubmit = this.handleSubmit.bind(this);
  13. }
  14. // 当选择框的值发生变化时触发
  15. handleChange(event) {
  16. // 更新组件状态,将选择框的值存储在state中
  17. this.setState({
  18. value: event.target.value });
  19. }
  20. // 表单提交时触发
  21. handleSubmit(event) {
  22. // 显示弹窗,展示选择的喜好
  23. alert('Your favorite flavor is: ' + this.state.value);
  24. event.preventDefault();
  25. }
  26. render() {
  27. return (
  28. <form onSubmit={
  29. this.handleSubmit}>
  30. <label>
  31. what website do you like?
  32. <select value={
  33. this.state.value} onChange={
  34. this.handleChange}>
  35. <option value="gg">Google</option>
  36. <option value="rn">aaa</option>
  37. <option value="tb">bbb</option>
  38. <option value="fb">Facebook</option>
  39. </select>
  40. </label>
  41. <input type="submit" value="提交" />
  42. </form>
  43. );
  44. }
  45. }
  46. ReactDOM.render(
  47. <FlavorForm />,
  48. document.getElementById('example')
  49. );
  • 一个表单组件FlavorForm,其中包含一个选择框一个提交按钮
  • 在组件的状态value中初始化为"coconut"
  • 选择框的值发生变化时,会触发handleChange方法来更新组件的状态
  • 当提交表单时,会触发handleSubmit方法来显示一个弹窗,展示选择的喜好。
  • 通过ReactDOM.renderFlavorForm组件渲染到id"example"的DOM元素中

React 事件

通过 onClick 事件来修改数据

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. class HelloMessage extends React.Component {
  4. constructor(props) {
  5. super(props);
  6. // 初始化组件状态
  7. this.state = {
  8. value: 'Hello react!'
  9. };
  10. // 绑定handleChange方法的上下文
  11. this.handleChange = this.handleChange.bind(this);
  12. }
  13. // 处理按钮点击事件
  14. handleChange(event) {
  15. // 更新组件状态,将value值设置为'hello,world'
  16. this.setState({
  17. value: 'hello,world' });
  18. }
  19. render() {
  20. var value = this.state.value;
  21. return (
  22. <div>
  23. {
  24. /* 按钮,点击时触发handleChange方法 */}
  25. <button onClick={
  26. this.handleChange}>点我</button>
  27. {
  28. /* 显示当前value的值 */}
  29. <h4>{
  30. value}</h4>
  31. </div>
  32. );
  33. }
  34. }
  35. // 将HelloMessage组件渲染到id为"example"的DOM元素中
  36. ReactDOM.render(
  37. <HelloMessage />,
  38. document.getElementById('example')
  39. );
  • 展示了一个按钮和一个标题。
  • 初始时,标题显示”Hello react!”。
  • 当按钮被点击时,会触发handleChange方法,该方法将组件状态中的value值更新为"hello,world"
  • 通过ReactDOM.renderHelloMessage组件渲染到id"example"的DOM元素中

在这里插入图片描述
在这里插入图片描述
当你需要从子组件中更新父组件的 state 时,你需要在父组件通过创建事件句柄 (handleChange) ,并作为 prop (updateStateProp) 传递到你的子组件上。

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. class Content extends React.Component {
  4. render() {
  5. return (
  6. <div>
  7. {
  8. /* 按钮,点击时触发传入的updateStateProp方法 */}
  9. <button onClick={
  10. this.props.updateStateProp}>点我</button>
  11. {
  12. /* 显示传入的myDataProp值 */}
  13. <h4>{
  14. this.props.myDataProp}</h4>
  15. </div>
  16. );
  17. }
  18. }
  19. class HelloMessage extends React.Component {
  20. constructor(props) {
  21. super(props);
  22. // 初始化组件状态
  23. this.state = {
  24. value: 'Hello react!'
  25. };
  26. // 绑定handleChange方法的上下文
  27. this.handleChange = this.handleChange.bind(this);
  28. }
  29. // 处理按钮点击事件
  30. handleChange(event) {
  31. // 更新组件状态,将value值设置为'hello,world!'
  32. this.setState({
  33. value: 'hello,world!' });
  34. }
  35. render() {
  36. var value = this.state.value;
  37. return (
  38. <div>
  39. {
  40. /* 渲染Content组件,传入value作为myDataProp,传入handleChange方法作为updateStateProp */}
  41. <Content myDataProp={
  42. value} updateStateProp={
  43. this.handleChange} />
  44. </div>
  45. );
  46. }
  47. }
  48. // 将HelloMessage组件渲染到id为"example"的DOM元素中
  49. ReactDOM.render(
  50. <HelloMessage />,
  51. document.getElementById('example')
  52. );
  • 这段代码中有两个组件:ContentHelloMessage
  • Content组件包含一个按钮和一个标题,根据myDataProp的值来显示标题的内容。
  • 按钮被点击时,触发updateStateProp方法
  • HelloMessage组件包含一个状态value,初始化为”Hello react!”。
  • 它也有一个handleChange方法,用于更新状态value的值
  • 在HelloMessage组件的render方法中,通过<Content>标签将Content组件渲染到DOM中,传递了value作为myDataProp的值,并将handleChange方法作为updateStateProp传递给Content组件。
  • 最后,通过ReactDOM.renderHelloMessage组件渲染到id为”example”的DOM元素中。
    在这里插入图片描述
    在这里插入图片描述

4)React Refs

React 列表 & Keys

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. // 定义一个数组
  4. const numbers = [1, 2, 3, 4, 5];
  5. // 使用map方法遍历数组,生成一个包含li元素的数组
  6. const listItems = numbers.map((number) =>
  7. <li>{
  8. number}</li>
  9. );
  10. // 将包含li元素的数组渲染为ul列表
  11. ReactDOM.render(
  12. <ul>{
  13. listItems}</ul>,
  14. document.getElementById('example')
  15. );

这段代码将一个数组numbers中的元素通过map方法遍历,生成一个包含li元素的新数组listItems
最后,通过ReactDOM.renderlistItems渲染为一个无序列表(ul元素)并挂载到id为"example"的DOM元素中。每个li元素的内容都是数组中对应的数字。
在这里插入图片描述
我们可以将以上实例重构成一个组件,组件接收数组参数,每个列表元素分配一个 key,不然会出现警告 a key should be provided for list items,意思就是需要包含 key:

  1. import React from 'react';
  2. import ReactDOM from 'react-dom';
  3. // 定义一个函数组件NumberList
  4. function NumberList(props) {
  5. // 从props中获取传入的数组
  6. const numbers = props.numbers;
  7. // 使用map方法遍历数组,生成一个包含li元素的新数组
  8. const listItems = numbers.map((number) =>
  9. // 使用number作为key属性,确保每个元素在列表中具有唯一的标识
  10. <li key={
  11. number.toString()}>
  12. {
  13. number}
  14. </li>
  15. );
  16. // 返回包含listItems的ul元素
  17. return (
  18. <ul>{
  19. listItems}</ul>
  20. );
  21. }
  22. const numbers = [1, 2, 3, 4, 5];
  23. // 渲染NumberList组件,并传入numbers作为props
  24. ReactDOM.render(
  25. <NumberList numbers={
  26. numbers} />,
  27. document.getElementById('example')
  28. );
  • 这段代码中定义了一个函数组件NumberList,它接受一个props参数。
  • 在函数组件中,我们从props中获取传入的数组numbers
  • 然后,使用map方法遍历数组,并生成一个包含li元素的新数组listItems
  • 注意,在每个li元素上设置了一个唯一的key属性以确保每个元素在列表中具有唯一的标识
  • 最后,函数组件返回一个包含listItems的ul元素
  • 通过ReactDOM.renderNumberList组件渲染到id为”example”的DOM元素中,同时将numbers作为numbers属性传递给组件。这样,列表中的每个数字将被渲染为一个li元素。
    在这里插入图片描述

Keys

Keys 可以在 DOM 中的某些元素被增加或删除的时候帮助 React 识别哪些元素发生了变化。

  1. const numbers = [1, 2, 3, 4, 5];
  2. const listItems = numbers.map((number) =>
  3. <li key={
  4. number.toString()}>
  5. {
  6. number}
  7. </li>
  8. );

一个元素的 key 最好是这个元素在列表中拥有的一个独一无二的字符串。通常,我们使用来自数据的 id 作为元素的 key:

  1. const todoItems = todos.map((todo) =>
  2. <li key={
  3. todo.id}>
  4. {
  5. todo.text}
  6. </li>
  7. );

当元素没有确定的 id 时,你可以使用他的序列号索引 index 作为 key:

  1. const todoItems = todos.map((todo, index) =>
  2. // 只有在没有确定的 id 时使用
  3. <li key={
  4. index}>
  5. {
  6. todo.text}
  7. </li>
  8. );

如果列表可以重新排序,我们不建议使用索引来进行排序,因为这会导致渲染变得很慢。

发表评论

表情:
评论列表 (有 0 条评论,114人围观)

还没有评论,来说两句吧...

相关阅读

    相关 gulp详细学习教程

    对网站资源进行优化,并使用不同浏览器测试并不是网站设计过程中最有意思的部分,但是这个过程中的很多重复的任务能够使用正确的工具自动完成,从而使效率大大提高,这是让很多开发者觉得有