React组件化开发(6)- ref的转发&Portals&Portals&StrictMode(7)
13.5ref的转发
在前面学习ref时说过,ref不能应用于函数式组件:
- 因为函数式组件没有实例,所以不能获取到对应的组件对象
但是,在开发中我们可能想要获取函数式组件中某个元素的DOM,这个时候我们应该如何操作呢:
- 注意能直接传入ref属性
- 通过forwardRef高阶组件;
import React, { PureComponent, createRef, forwardRef } from 'react'
class Home extends PureComponent {
render() {
return (<h3>Home</h3>)
}
}
// forwardRef 高阶组件,里面做了增强ref
const About = forwardRef(function About(props, ref) {
return <h4 ref={ref}>About</h4>
})
export default class App extends PureComponent {
constructor() {
super();
this.state = {
HomeRef: createRef(),
H3Ref: createRef(),
AboutRef: createRef()
}
}
render() {
return (
<div>
<h3 ref={this.state.H3Ref}>app</h3>
<Home ref={this.state.HomeRef} />
<About ref={this.state.AboutRef} />
<button onClick={e => this.printRef()}>打印ref</button>
</div>
)
}
printRef() {
console.log(this.state.HomeRef.current);
console.log(this.state.H3Ref.current);
console.log(this.state.AboutRef.current);
}
}
14.Portals的使用
某些情况下,我们希望渲染的内容独立于父组件,甚至是独立于当前挂载到的DOM元素中(默认都是挂载到id为root的DOM元素上的)。
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案:
- 第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment;
- 第二个参数(container)是一个 DOM 元素;
通常来讲,当你从组件的 render 方法返回一个元素时,该元素将被挂载到 DOM 节点中离其最近的父节点
然而,有时候将子元素插入到 DOM 节点中的不同位置也是有好处的:
14.1Portals案例
我们准备开发一个Modal组件,它可以将它的子组件渲染到屏幕的中间位置
App.js
import React, { PureComponent, } from 'react'
import ReactDOM from "react-dom"
import "./portals.css"
class Modal extends PureComponent {
render() {
console.log(this.props.children[0]);
console.log(this.props);
return (
ReactDOM.createPortal(
this.props.children,
document.getElementById("modal")
)
)
}
}
export default class App extends PureComponent {
render() {
return (
<div>
<Modal>
<h1>TitleCenter</h1>
</Modal>
</div>
)
}
}
html 结构:
样式:
15.fragment
在之前的开发中,我们总是在一个组件中返回内容时包裹一个div元素:
我们又希望可以不渲染这样一个div应该如何操作呢?
- 使用Fragment
- Fragment 允许你将子列表分组,而无需向 DOM 添加额外节点;
React还提供了Fragment的短语法:
- 它看起来像空标签 <> </>;
- 但是,如果我们需要在Fragment中添加key,那么就不能使用短语法
import React, { PureComponent } from 'react'
class Home extends PureComponent {
render() {
return (
<React.Fragment>
<h2>我-Fragment</h2>
<ul>
<li>你好</li>
<li>你好</li>
<li>你好</li>
</ul>
</React.Fragment>
)
}
}
class About extends PureComponent {
constructor(props) {
super(props);
this.state = {
list: [{ name: "雷利", age: 40 }, { name: "罗杰", age: 42 }, { name: "御田", age: 39 }]
}
}
render() {
return (
<div>
{
this.state.list.map((item, index) => {
// return (
// 使用了Fragment的短语法就能添加key
// < key={item.name}>
// <div>{item.name}</div>
// <p>{item.age}</p>
// </>
// )
return (
<React.Fragment key={item.name}>
<div>{item.name}</div>
<p>{item.age}</p>
</React.Fragment>
)
})
}
</div>
)
}
}
export default class App extends PureComponent {
render() {
return (
<div>
<Home />
<About />
</div>
)
}
}
16.StrictMode
StrictMode 是一个用来突出显示应用程序中潜在问题的工具。
- 与 Fragment 一样,StrictMode 不会渲染任何可见的 UI。
- 它为其后代元素触发额外的检查和警告。
- 严格模式检查仅在开发模式下运行; 它们不会影响生产构建 。
你可以为应用程序的任何部分启用严格模式:
- 不会对Home启用严格模式检查
- 对所有包裹在StrictMode里面的内容开启严格模式检查
16.1严格模式检测的是什么?
严格模式到底检查的是什么:
- 识别不安全的生命周期
- 使用过时的ref
- 使用废弃的findDOMNode方法的警告
检测意外的副作用
- 这个组件的constructor会被调用两次;
- 这是严格模式下故意进行的操作,让你来查看在这里写的一些逻辑代码被调用多次时,是否会产生一些副作用;
- 在生产环境中,是不会被调用两次的;
检测过时的context API
- 早期的Context是通过static属性声明Context对象属性,通过getChildContext返回Context对象等方式来使用Context的
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭