经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » React » 查看文章
react中context传值和生命周期详解
来源:jb51  时间:2023/3/20 8:39:54  对本文有异议

假设:

项目中存在复杂组件树:

context传值用途

数据是通过 props 属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。

Context传值优点

Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props。

何时使用 Context

Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言。

ContextAPI

  1. 1.React.createContext API
  2. 功能:
  3. 创建一个 Context 对象。
  4. //代码
  5. //创建context对象的
  6. import React from 'react'
  7. let context=React.createContext();
  8. export default context;
  9. 2.Context.Provider API
  10. 功能:
  11. Provider context对象提供的内置组件 限定在某个作用域中使用context传值。
  12. 限定作用域传值。
  13. 3.Context.Consumer
  14. context对象的内置组件
  15. <MyContext.Consumer>
  16. {value => /* 基于 context 值进行渲染*/}
  17. </MyContext.Consumer>
  18. 作用:监听订阅的context变更,
  19. 这个函数接收当前的 context 值,返回一个 React 节点。

项目案例:主题色切换。

  1. 1.创建context.js文件
  2. 创建context对象 用来做context传值。
  3. //创建context对象的
  4. import React from 'react'
  5. export default React.createContext();
  1. 2。使用context找到限定范围使用内置组件Provider
  2. {/* 使用Provider 内置组件限定context范围 */}
  3. {/* value 必填 context传递的值 */}
  4. <ThemeContext.Provider>
  5. <div className="Admin">
  6. <div className="LeftMenu">
  7. <LeftMenu></LeftMenu>
  8. </div>
  9. <div className="RightContent">
  10. <div className="RightContent-top">
  11. <TopHeader></TopHeader>
  12. </div>
  13. <div className="RightContent-bottom">
  14. <Dashborder></Dashborder>
  15. </div>
  16. </div>
  17. </ThemeContext.Provider>

浏览器报错:

  1. 3.在使用context的组件中进行订阅
  2. 左侧菜单组件
  3. import React, { Component } from "react";
  4. console.log(Component);
  5. //引入context对象
  6. import ThemeContext from "../components/context";
  7. class LeftMenu extends Component {
  8. constructor(props) {
  9. super(props);
  10. this.state = {};
  11. }
  12. render() {
  13. return (
  14. <>
  15. <div>左侧菜单</div>
  16. </>
  17. );
  18. }
  19. }
  20. //class类组件存在contextType 绑定context对象
  21. LeftMenu.contextType = ThemeContext;

组件中绑定context之后使用:

意味着订阅context组件的内部使用this.context获取。

  1. render() {
  2. //获取context
  3. let theme = this.context;
  4. return (
  5. <>
  6. <div className={theme}>左侧菜单</div>
  7. </>
  8. );
  9. }

固定主体修改为动态主体

  1. 修改了context文件代码
  2. //定义默认主体色
  3. export const themes = {
  4. dark: {
  5. backgroundColor: "#000",
  6. color: "#fff",
  7. },
  8. light: {
  9. backgroundColor: "#fff",
  10. color: "#000",
  11. },
  12. };
  13. //创建context对象的
  14. import React from "react";
  15. export const ThemeContext = React.createContext();
  1. app.js文件中获取主题,动态切换主题。使用主题变量
  2. constructor(props) {
  3. super(props);
  4. this.state = {
  5. //将固定的主体设置为state状态
  6. themeType: "dark",//控制主体切换
  7. nowTheme: themes["dark"],//获取当前默认主体
  8. };
  9. }
  10. render() {
  11. //解构获取
  12. let { nowTheme } = this.state;
  13. return (
  14. <>
  15. {/* 使用Provider 内置组件限定context范围 */}
  16. {/* value 必填 context传递的值 */}
  17. <ThemeContext.Provider value={nowTheme}>

订阅组件中使用this.context获取订阅

  1. render() {
  2. //获取context
  3. let { backgroundColor, color } = this.context;
  4. return (
  5. <>
  6. //直接绑定行内css
  7. <div style={{ backgroundColor: backgroundColor, color: color }}>
  8. 左侧菜单
  9. </div>
  10. </>
  11. );
  12. }

用户点击其他组件修改主题的按钮来变更主题

  1. 注意:不能直接使用this.context修改变量值
  2. //可以在provider组件上 value中携带修改函数传递。在订阅组件中获取修改方法,执行反向传递值。
  3. //修改主题变量方法
  4. changeTheme(type) {
  5. console.log("测试", type);
  6. this.setState({ themeType: type, nowTheme: themes[type] });
  7. }
  8. render() {
  9. //解构获取
  10. let { nowTheme } = this.state;
  11. return (
  12. <>
  13. {/* 使用Provider 内置组件限定context范围 */}
  14. {/* value 必填 context传递的值 */}
  15. <ThemeContext.Provider
  16. value={{ ...nowTheme, handler: this.changeTheme.bind(this) }}
  17. >
  18. <div className="Admin">
  19. <div className="LeftMenu">
  20. <LeftMenu></LeftMenu>
  21. </div>
  22. <div className="RightContent">
  23. <div className="RightContent-top">
  24. <TopHeader></TopHeader>
  25. </div>
  26. <div className="RightContent-bottom">
  27. <Dashborder></Dashborder>
  28. </div>
  29. </div>
  30. </div>
  31. </ThemeContext.Provider>
  32. </>
  33. );
  34. //在订阅组件中直接使用
  35. //修改主题的方法
  36. change(themeType) {
  37. console.log(themeType);
  38. //获取provider传递方法
  39. let { handler } = this.context;
  40. handler(themeType);
  41. }
  42. render() {
  43. let { themeButton } = this.state;
  44. return (
  45. <>
  46. <div>
  47. <span>主题色:</span>
  48. <div>
  49. {/* 控制左侧菜单和上header背景色 */}
  50. {themeButton.map((item, index) => {
  51. return (
  52. <button key={index} onClick={this.change.bind(this, item.type)}>
  53. {item.name}
  54. </button>
  55. );
  56. })}
  57. </div>
  58. </div>
  59. </>
  60. );

添加自定义颜色

  1. {/* 颜色选择器 */}
  2. 背景色:
  3. <input
  4. type="color"
  5. name="selectbgColor"
  6. value={selectbgColor}
  7. onChange={this.changeColor.bind(this)}
  8. />
  9. 字体色:
  10. <input
  11. type="color"
  12. name="selectColor"
  13. value={selectColor}
  14. onChange={this.changeColor.bind(this)}
  15. />
  16. <button onClick={this.yesHandler.bind(this)}>确认</button>
  17. //代码区域操作事件向父级传递参数
  18. //确认修改
  19. yesHandler() {
  20. let { myhandler } = this.context;
  21. let { selectbgColor, selectColor } = this.state;
  22. console.log(selectbgColor, selectColor);
  23. myhandler(selectbgColor, selectColor);
  24. }

添加监听context变化

  1. {/*监听context value值*/}
  2. <ThemeContext.Consumer>
  3. {(value) => {
  4. let { backgroundColor, color } = value;
  5. return (
  6. <>
  7. <span>背景色:{backgroundColor}</span>
  8. <span>文字色:{color}</span>
  9. </>
  10. );
  11. }}
  12. </ThemeContext.Consumer>

类组件的生命周期

组件生命周期解释:组件初始化到销毁整个过程。

生命周期三类:

  • Mounting(挂载):已插入真实 DOM
  • Updating(更新):正在被重新渲染
  • Unmounting(卸载):已移出真实 DOM
  1. 第一个阶段:
  2. 代码演示第一个阶段初始化挂载阶段
  3. import React, { Component } from "react";
  4. class App extends Component {
  5. constructor(props) {
  6. super(props);
  7. this.state = {};
  8. console.log("初始化");
  9. }
  10. componentDidMount() {
  11. console.log("挂载完成");
  12. }
  13. render() {
  14. console.log("渲染");
  15. return (
  16. <>
  17. <div>测试</div>
  18. </>
  19. );
  20. }
  21. }
  22. export default App;

添加了挂载之前周期

  1. UNSAFE_componentWillMount() {
  2. console.log("挂载之前");
  3. }
  4. //18.x 版本中UNSAFE_ 前缀

  1. 第二个阶段:更新阶段
  2. 能触发类组件更新 props state

添加了更新之前周期

  1. componentWillUpdate() {
  2. console.log("更新之前");
  3. }

第三阶段卸载:

  1. //卸载周期
  2. componentWillUnmount() {
  3. console.log("组件卸载");
  4. }

常用周期:

测试完成之后:18版本直接使用周期以上三个。

  1. react推荐网络请求在componentDidMount
  2. 卸载清除副作用 componentWillUnmount

确认当前组件是否更新周期

  1. //确认是否更新周期
  2. //必须带返回值 true false
  3. //提升性能
  4. shouldComponentUpdate(nextProps, nextState, nextContext) {
  5. console.log(nextProps);
  6. if (nextProps.name == this.props.name) return false;
  7. else return true;
  8. }
  9. 不写该周期默认是执行更新
  1. 1.componentWillMount() - 在染之前执行,在客户端和服务器端都会执行.
  2. 2.componentDidMount() - 是挂在完成之后执行一次
  3. 3.componentWillReceiveProps() - 当从父类接收到 props 并且在调用另一个渲染器器之前调用。4.shouldComponentUpdatel) -根据特定条件返回 true false如果你希望更新组件,请返回true 否则返它返回 false
  4. 5.componentWillUpdate() - 是当前组件stateprops发生变化之前执行
  5. 6.componentDidUpdate()-是当前组件stateprops发生变化执行
  6. 7.componentWillUnmount0) - DOM 卸载组件后调用。用于清理内存空间

到此这篇关于react中context传值和生命周期的文章就介绍到这了,更多相关react context传值和生命周期内容请搜索w3xue以前的文章或继续浏览下面的相关文章希望大家以后多多支持w3xue!

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号