期刊介绍
期刊导读
- 08/17各种无线通信技术在车联网中有什么应用
- 08/1730分钟精通十种React组件之间通信的方法
- 08/17深圳华强王瑛:信息通信企业向产业链高端演进
- 08/17院士专家热议新一代信息通信产业发展
- 08/17承德市人民政府与中国信息通信研究院签署战略
30分钟精通十种React组件之间通信的方法(2)
6. Context
通常一个前端应用会有一些\"全局\"性质的数据,比如当前登陆的用户信息、ui主题、用户选择的语言等等。这些全局数据,很多组件可能都会用到,当组件层级很深时,用我们之前的方法,就得通过props一层一层传递下去,这显然太麻烦了,看下面的示例:
class App extends { render() { return ; }}function Toolbar(props) { return ( );}class ThemedButton extends { render() { return ; }}
上面的例子,为了让我们的Button元素拿到主题色,我们必须把theme作为props,从App传到Toolbar,再从Toolbar传到ThemedButton,最后Button从父组件ThemedButton的props里终于拿到了主题theme。假如我们不同组件里都有用到Button,就得把theme向这个例子一样到处层层传递,麻烦至极。
因此react为我们提供了一个新api:Context,我们用Context改写下上例
const ThemeContext = ('light');class App extends { render() { return ( <> > ); }}function Toolbar() { return ( );}class ThemedButton extends { static contextType = ThemeContext; render() { return ; }}
简单的解析一下:
- 创建了一个Context对象,假如某个组件订阅了这个对象,当react去渲染这个组件时,会从离这个组件最近的一个Provider组件中读取当前的context值
- : 每一个Context对象都有一个Provider属性,这个属性是一个react组件。在Provider组件以内的所有组件都可以通过它订阅context值的变动。具体来说,Provider组件有一个叫value的prop传递给所有内部组件,每当value的值发生变化时,Provider内部的组件都会根据新value值重新渲染
- 那内部的组件该怎么使用这个context对象里的东西呢?a. 假如内部组件是用class声明的有状态组件:我们可以把Context对象赋值给这个类的属性contextType,如上面所示的ThemedButton组件 class ThemedButton extends React.Component { static contextType = ThemeContext; render() { const value = return
最后提一句,context对于解决react组件层级很深的props传递很有效,但也不应该被滥用。只有像theme、language等这种全局属性(很多组件都有可能依赖它们)时,才考虑用context。如果只是单纯为了解决层级很深的props传递,可以直接用component composition
7. Portals
Portals也是react提供的新特性,虽然它并不是用来解决组件通信问题的,但因为它也涉及到了组件通信的问题,所以我也把它列在我们的十种方法里面。
Portals的主要应用场景是:当两个组件在react项目中是父子组件的关系,但在HTML DOM里并不像是父子元素的关系。
举个例子,有一个父组件Parent,它里面包含了一个子组件Tooltip,虽然在react层级上它们是父子关系,但我们希望子组件Tooltip渲染的元素在DOM中直接挂载在body节点里,而不是挂载在父组件的元素里。这样就可以避免父组件的一些样式(如overflow:hidden、z-index、position等)导致子组件无法渲染成我们想要的样式。
如下图所示,父组件是这个红色框的范围,并且设置了overflow:hidden,这时候我们的Tooltip元素超出了红色框的范围就被截断了。
怎么用portals解决呢?
首先,修改html文件,给portals增加一个节点
然后我们创建一个可复用的portal容器,这里使用了react hooks的语法,看不懂的先过去看下我另外一篇讲解react hooks的文章:30分钟精通React今年最劲爆的新特性——React Hooks
import { useEffect } from \"react\";import { createPortal } from \"react-dom\";const Portal = ({children}) => { const mount = (\"portal-root\"); const el = (\"div\"); useEffect(() => { (el); return () => (el); }, [el, mount]); return createPortal(children, el)};export default Portal;
最后在父组件中使用我们的portal容器组件,并将Tooltip作为children传给portal容器组件
文章来源:《信息通信技术与政策》 网址: http://www.xxtxzz.cn/zonghexinwen/2020/0817/599.html