当今最流行的JavaScript库之一React,因其强大的组件化开发能力而备受欢迎。React官方文档是学习和掌握React的重要资源之一,它提供了全面的指南、API文档和示例代码。因为现在的公司使用React进行开发项目,遂打算重新跟着文档学一遍React。
jsxReactDOM.render(
<Game />, // 提供html标签或者React组件标签,都可以被解析
document.getElementById('root') // 插入到的节点
);
返回的是一个对象,无标记值,但是提供了updater和isMounted
JSX语法会自动将html标签转换成React.createElement
JSX文件,每次需引入React插件,因为转换时,会用到React.createElement
jsx// 转换前
const elObj=<div>result</div>
// 转换后
const elObj = /*#__PURE__*/React.createElement("div", null, "result");
返回的是一个对象,介绍几个常用值:
js$$typeof: Symbol(react.element)
key: null
props: {a1: "a1", a2: "a2", a3: ƒ}
ref: "t1"
type: class Board
_owner: FiberNode {tag: 1, key: null, stateNode: Game, elementType: ƒ, type: ƒ, …}
_store: {validated: false}
_self: Game {props: {…}, context: {…}, refs: {…}, updater: {…}, _reactInternalFiber: FiberNode, …}
_source: {fileName: "/Users/ccz/Public/student-project/cs/react-website-student/src/index.js", lineNumber: 50, columnNumber: 23}
__proto__: Object
最后,可以看下React文档,里面有一段 Class components should always call the base constructor with props.
另外附上一个高分回答
通常会将代表事件的监听 prop 命名为on[Event],将处理事件的监听方法命名为 handle[Event]这样的格式
组件名称必须以大写字母开头。
React 会将以小写字母开头的组件视为原生 DOM 标签。例如,
jsximport React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
context.js
js// 建议使用单独js,否则容易出现ESM循环引用问题
import React from 'react'
export const ThemeContext = React.createContext('light')
app.jsx
jsximport { ThemeContext } from './context'
import Child from './child'
class App extends React.Component {
render () {
return (
<ThemeContext.Provider value="dark">
<Child/>
</ThemeContext.Provider>
)
}
}
child.jsx
jsximport React from 'react'
import { ThemeContext } from './context'
class Child extends React.Component {
static contextType = ThemeContext;
render () {
console.log('context',this.context)
return (
<div> </div>
)
}
}
export default Board
child.jsx
jsximport { ThemeContext } from './context'
const Child = (props) => {
return (
<ThemeContext.Consumer>
{ value =>{
console.log('value',value)
return (
<div> </div>
)
}}
</ThemeContext.Consumer>
)
}
React DevTools 使用该字符串来确定 context 要显示的内容。 示例,下述组件在 DevTools 中将显示为 MyDisplayName:
jsxconst MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';
<MyContext.Provider> // "MyDisplayName.Provider" 在 DevTools 中
<MyContext.Consumer> // "MyDisplayName.Consumer" 在 DevTools 中
多个Provider的情况下,可以创建多个对应的Consumer接收内容
当value更新时,Provider包裹下的所有子组件都将被更新。 Provider value 直接赋值为对象时,建议抽离为state,直接使用对象赋值,会造成无用的元素更新,造成性能消耗。
自 React 16 起,任何未被错误边界捕获的错误将会导致整个 React 组件树被卸载
通过最外层组件的 componentDidCatch生命周期进行捕获错误
jsximport React from 'react'
class ErrorBoundary extends React.Component {
componentDidCatch(error, errorInfo) {
// 你同样可以将错误日志上报给服务器
console.log(error, errorInfo);
}
render() {
return this.props.children;
}
}
export default ErrorBoundary
jsximport React, { Suspense } from 'react';
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const AnotherComponent = React.lazy(() => import('./AnotherComponent'));
const MyComponent = () => (
<div>
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<section>
<OtherComponent />
<AnotherComponent />
</section>
</Suspense>
</MyErrorBoundary>
</div>
);
注意:在React中ref属性仅仅用作获取dom值,在React16.3前,ref仅能拿到当前元素的dom情况。 当然我们可以通过定义其他function props去获取对应的dom
react内置高阶组件,可以透传ref,ref的值可以直接指定dom,也可以传对象
jsxconst FancyButton = React.forwardRef((props, ref) => (
<button ref={ref} className="FancyButton">
{props.children}
</button>
));
// 你可以直接获取 DOM button 的 ref
const ref = React.createRef();
<FancyButton ref={ref}>Click me!</FancyButton>;
注意:在使用forwardRef时,应当将其视为一个破坏性更改,因为该组件会有明显不同的行为。 当我们使用高阶组件(HOC),我们在高阶组件使用ref,拿到的是高阶组件ref的实例,若我们想拿取Component的实例,需要定义额外的props字段。使用React.forwardRef可以直接使用ref 当做props进行透传。
1.不要改变原始组件。使用组合 不要试图在 HOC 中修改组件原型(或以其他方式改变它)。
jsfunction logProps(InputComponent) {
InputComponent.prototype.componentDidUpdate = function(prevProps) {
console.log('Current props: ', this.props);
console.log('Previous props: ', prevProps);
};
// 返回原始的 input 组件,暗示它已经被修改。
return InputComponent;
}
// 每次调用 logProps 时,增强组件都会有 log 输出。
const EnhancedComponent = logProps(InputComponent);
2.将不相关的 props 传递给被包裹的组件
HOC 为组件添加特性。自身不应该大幅改变约定。HOC 返回的组件与原组件应保持类似的接口。 HOC 应该透传与自身无关的 props。大多数 HOC 都应该包含一个类似于下面的 render 方法:
jsxrender() {
// 过滤掉非此 HOC 额外的 props,且不要进行透传
const { extraProp, ...passThroughProps } = this.props;
// 将 props 注入到被包装的组件中。
// 通常为 state 的值或者实例方法。
const injectedProp = someStateOrInstanceMethod;
// 将 props 传递给被包装组件
return (
<WrappedComponent
injectedProp={injectedProp}
{...passThroughProps}
/>
);
}
3.包装显示名称以便轻松调试
最常见的方式是用 HOC 包住被包装组件的显示名称。比如高阶组件名为 withSubscription,并且被包装组件的显示名称为 CommentList,显示名称应该为
jsxWithSubscription(CommentList)
function withSubscription(WrappedComponent) {
class WithSubscription extends React.Component {/* ... */}
WithSubscription.displayName = `WithSubscription(${getDisplayName(WrappedComponent)})`;
return WithSubscription;
}
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component';
}
4.不要在 render 方法中使用 HOC
通常,你不需要考虑这点。但对 HOC 来说这一点很重要,因为这代表着你不应在组件的 render 方法中对一个组件应用 HOC:
jsrender() {
// 每次调用 render 函数都会创建一个新的 EnhancedComponent
// EnhancedComponent1 !== EnhancedComponent2
const EnhancedComponent = enhance(MyComponent);
// 这将导致子树每次渲染都会进行卸载,和重新挂载的操作!
return <EnhancedComponent />;
}
5.务必复制静态方法
在 JSX 中,你也可以使用点语法来引用一个 React 组件。当你在一个模块中导出许多 React 组件时,这会非常方便。
jsximport React from 'react';
const MyComponents = {
DatePicker: function DatePicker(props) {
return <div>Imagine a {props.color} datepicker here.</div>;
}
}
function BlueDatePicker() {
return <MyComponents.DatePicker color="blue" />;}
与标签相邻的空行均会被删除,文本字符串之间的新行会被压缩为一个空格。因此以下的几种方式都是等价的:
jsx<div>Hello World</div>
<div>
Hello World
</div>
<div>
Hello
World
</div>
<div>
Hello World
</div>
false, null, undefined, and true 是合法的子元素。但它们并不会被渲染。以下的 JSX 表达式渲染结果相同:
jsx<div />
<div></div>
<div>{false}</div>
<div>{null}</div>
<div>{undefined}</div>
<div>{true}</div>
反之,如果你想渲染 false、true、null、undefined 等值,你需要先将它们转换为字符串:
jsx<div>My JavaScript variable is {String(myVariable)}.</div>
Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案,Portal 组件即使不在父组件的dom节点内,父组件仍然能够捕获其事件
jsximport React from 'react'
import ReactDOM from 'react-dom'
const Modal = (props) => {
return ReactDOM.createPortal(
<div className="modal-container">{props.children}</div>,
document.querySelector('body')
);
}
export default Modal
本文作者:BARM
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!