React | React组件化开发(二)

简介: React | React组件化开发(二)

四、React组件插槽用法

React中的插槽(slot)

  • 在开发中 我们抽取了一个组件 但是为了让这个组件具备更强的通用性 我们不能将组件中的内容限制为固定的div span等等这些元素
  • 我们应该让使用者可以决定某一块区域到底存放什么内容

88a443a8b0804ae89e3cee2a2c764679.png

  • 这种需求在Vue当中有一个固定的做法是通过slot来完成的 那么在React中呢?
  • React对于这种需要插槽的情况非常灵活 有两种方案可以实现
  • 组件的children子元素
  • props属性传递React元素

children实现插槽

  • 每个组件都可以获取到props.children: 它包含组件的开始标签和结束标签之间的内容.

6e4f639da9cd4eb8924d5dea2c14f24a.png

39f2572fa99f46049553b97dad574956.png

props实现插槽

  • 通过children实现的方案虽然可行 但是有一个弊端: 通过索引值获取传入的元素很容易出错 不能精准的获取传入的原生
  • 另外一个种方案就是使用 props 实现
  • 通过具体的属性名 可以让我们在传入和获取时更加的精准

8eaa94e9556a40aaa239e66ce53a8f43.png

8e96b0e2185349a7b918c6f528ae8a3c.png

五、React非父子的通信

Context应用场景

  • 非父子组件数据的共享:
  • 在开发中 比较常见的数据传递方式是通过props属性自上而下(由父到子)进行传递
  • 但是对于有一些场景: 如一些数据需要在多个组件中进行共享(地区偏好、UI主题、用户登录状态、用户信息等)
  • 如果我们在顶层的App中定义这些信息 之后一层层传递下去 那么对于一些中间层不需要数据的组件来说 是一种冗余的操作


  • 我们实现一个一层层传递的案例:


  • 我这边顺便补充一个小的知识点:Spread Attributes

033c7250cbae416c8eedfb8cb3258114.png

但是 如果层级更多的话 一层层传递是非常麻烦 并且代码是非常冗余的

  • React提供了一个API:Context
  • Context 提供了一种在组件之间共享此类值的方式 而不必显式地通过组件树的逐层传递 props
  • Context 设计目的是为了共享那些对于一个组件树而言是“全局”的数据 如 当前认证的用户 主题或首选语言

Context相关API

React.createContext

  • 创建一个需要共享的Context对象
  • 如果一个组件订阅了Context 那么这个组件会从离自身最近的那个匹配的 Provider 中读取到当前的context值
  • defaultValue是组件在顶层查找过程中没有找到对应的Provider 那么就使用默认值

b475572c88b8481eb60e7d6df17c22aa.png

Context.Provider


  • 每个 Context 对象都会返回一个 Provider React 组件 它允许消费组件订阅 context 的变化
  • Provider 接收一个 value 属性 传递给消费组件
  • 一个 Provider 可以和多个消费组件有对应关系
  • 多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据
  • 当 Provider 的 value 值发生变化时 它内部的所有消费组件都会重新渲染

9c2e7c30ac284547aeaa991e2243bf50.png

Class.contextType


  • 挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象
  • 这能让你使用 this.context 来消费最近 Context 上的那个值
  • 你可以在任何生命周期中访问到它,包括 render 函数中

c7335df72caa436f88ede45d9e17b07c.png

Context.Consumer


  • React 组件也可以订阅到 context 变更.这能让你在 函数式组件 中完成订阅 context
  • 这里需要 函数作为子元素(function as child)这种做法
  • 这个函数接收当前的 context 值,返回一个 React 节点

71fc8285c9f842abbd0e2db0e55283ea.png

  • 什么时候使用Context.Consumer?
  • 当使用value的组件是一个函数式组件时
  • 当组件中需要使用多个Context时

六、setState的使用详解

为什么使用setState

开发中我们并不能直接通过修改state的值来让界面发生更新

  • 因为我们修改了state之后 希望React根据最新的State来重新渲染界面 但是这种方式的修改React并不知道数据发生了变化
  • React并没有实现类似于Vue2中的Object.defineProperty或者Vue3中的Proxy的方式来监听数据的变化
  • 我们必须通过setState来告知React数据已经发生了变化


在组件中并没有实现setState的方法,为什么可以调用呢?


  • 原因很简单,setState方法是从Component中继承过来的

5971b22a7a174a558cb0a7bbd91b4037.png

setState异步更新

  • setState的更新是异步的?
  • 最终打印结果是Hello World
  • 可见setState是异步的操作 我们并不能在执行完setState之后立马拿到最新的state的结果

2bd5057b65984e6096ef0d0ff6fe184e.png

  • 为什么setState设计为异步呢?
  • setState设计为异步其实之前在GitHub上也有很多的讨论
  • React核心成员(Redux的作者)Dan Abramov也有对应的回复 有兴趣的同学可以参考一下


  • 总结:setState设计为异步,可以显著的提升性能
  • 如果每次调用 setState都进行一次更新 那么意味着render函数会被频繁调用 界面重新渲染 这样效率是很低
  • 最好的办法应该是获取到多个更新 之后进行批量更新


  • 如果同步更新了state 但是还没有执行render函数 那么state和props不能保持同步
  • state和props不能保持一致性 在开发中产生很多的问题

如何获取异步的结果

  • 如何可以获取到更新后的值呢?
  • setState(partialState, callback)
  • setState接受两个参数: 第二个参数是一个回调函数 这个回调函数会在更新后会执行
  • setState的回调

42ab288f11104032b2a466789a94f44e.png

  • 当然,我们也可以在生命周期函数

7b5956a69e91479fa4302237ba7da3c9.png

setState一定是异步吗?(React18之前)

  • 在setTimeout中的更新

d297b612cc5d473588c474238b16d72d.png

原生DOM事件

6367862007f14f4a937a93376d73277b.png

  • 其实分成两种情况:
  • 在组件生命周期或React合成事件中,setState是异步
  • 在setTimeout或者原生dom事件中,setState是同步

setState默认是异步的(React18之后)

  • 在React18之后 默认所有的操作都被放到了批处理中(异步处理)

c1eb053b0cf54717a4b1e58b939aedf5.png

  • 如果希望代码可以同步拿到 则需要执行特殊的flushSync操作

f611af08bd6249ed855bc926b7892357.png

相关文章
|
3月前
|
前端开发 JavaScript API
React开发需要了解的10个库
本文首发于微信公众号“前端徐徐”,介绍了React及其常用库。React是由Meta开发的JavaScript库,用于构建动态用户界面,广泛应用于Facebook、Instagram等知名网站。文章详细讲解了Axios、Formik、React Helmet、React-Redux、React Router DOM、Dotenv、ESLint、Storybook、Framer Motion和React Bootstrap等库的使用方法和应用场景,帮助开发者提升开发效率和代码质量。
145 4
React开发需要了解的10个库
|
5月前
|
设计模式 存储 前端开发
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
React开发设计模式及原则概念问题之自定义Hooks的作用是什么,自定义Hooks设计时要遵循什么原则呢
|
3月前
|
前端开发 JavaScript 开发者
React 组件化开发最佳实践
【10月更文挑战第4天】React 组件化开发最佳实践
73 4
|
4月前
|
XML 移动开发 前端开发
使用duxapp开发 React Native App 事半功倍
对于Taro的壳子,或者原生React Native,都会存在 `android` `ios`这两个文件夹,而在duxapp中,这些文件夹的内容是自动生成的,那么对于需要在这些文件夹中修改的配置内容,例如包名、版本号、新架构开关等,都通过配置文件的方式配置了,而不需要需修改具体的文件
|
4月前
|
资源调度 JavaScript 前端开发
使用vite+react+ts+Ant Design开发后台管理项目(二)
使用vite+react+ts+Ant Design开发后台管理项目(二)
|
4月前
|
存储 前端开发 JavaScript
react 组件化
【9月更文挑战第2天】react 组件化
43 5
|
5月前
|
开发者 自然语言处理 存储
语言不再是壁垒:掌握 JSF 国际化技巧,轻松构建多语言支持的 Web 应用
【8月更文挑战第31天】JavaServer Faces (JSF) 框架提供了强大的国际化 (I18N) 和本地化 (L10N) 支持,使开发者能轻松添加多语言功能。本文通过具体案例展示如何在 JSF 应用中实现多语言支持,包括创建项目、配置语言资源文件 (`messages_xx.properties`)、设置 `web.xml`、编写 Managed Bean (`LanguageBean`) 处理语言选择,以及使用 Facelets 页面 (`index.xhtml`) 显示多语言消息。通过这些步骤,你将学会如何配置 JSF 环境、编写语言资源文件,并实现动态语言切换。
51 1
|
5月前
|
JavaScript 前端开发 安全
[译] 使用 TypeScript 开发 React Hooks
[译] 使用 TypeScript 开发 React Hooks
|
5月前
|
前端开发 JavaScript
React Server Component 使用问题之添加jsx的组件化能力,如何操作
React Server Component 使用问题之添加jsx的组件化能力,如何操作
|
5月前
|
开发者 Java
JSF EL 表达式:乘技术潮流之风,筑简洁开发之梦,触动开发者心弦的强大语言
【8月更文挑战第31天】JavaServer Faces (JSF) 的表达式语言 (EL) 是一种强大的工具,允许开发者在 JSF 页面和后台 bean 间进行简洁高效的数据绑定。本文介绍了 JSF EL 的基本概念及使用技巧,包括访问 bean 属性和方法、数据绑定、内置对象使用、条件判断和循环等,并分享了最佳实践建议,帮助提升开发效率和代码质量。
59 0