1、无障碍
1、语义化的html
1、语义化的 HTML 是无障碍辅助功能网络应用的基础
2、比如当在 JSX 中使用
-
,
-
和
-
)和 HTML 时。 在这种情况下,我们应该使用
React Fragments 来组合各个组件。
-
和
2、无障碍表单
1、标记
所有的 HTML 表单控制,例如 和 ,都需要被标注来实现无障碍辅助功能。我们需要提供屏幕朗读器以解释性标注。
2、键盘焦点
在 DOM 中,当前被选中来接受键盘信息的元素。我们可以在各处看到键盘焦点
3、跳过机制
跳转链接(Skiplinks),或者说跳转导航链接(Skip Navigation Links)是一种隐藏的导航链接,它只会在使用键盘导航时可见
2、代码分割
1、出现原因
1、随着应用变大,或者集合了第三方的库,代码包体积会变大。加载时间也会变长
2、为了避免大体积的代码包,前期应该对代码包分割
2、实现
3、webpack可以提供这个功能
4、可以创建多个包,并在运行时动态加载
5、可以懒加载用户需要的代码
3、import
1、webpack解析到的时候会自动代码分割
2、需要确定babel能够动态解析import,而不是转换
3、需要babel的插件:@babel/plugin-syntax-dynamic-import
4、懒加载
const OtherComponent = React.lazy(() => import('./OtherComponent'));
组件首次渲染时,会自动导入包含这个组件的包
1、接受一个函数,动态调用import
2、返回一个promise(异步相关),会resolve一个default export react的组件
3、在suspense组建里面渲染这个组件,
4、suspense会有一个fallback属性,里面接受组件
5、基于路由的代码分割
6、命名导出
1、懒加载只支持默认导出,也就是export default 或者 export 「some as default」
2、如果支持命名导出,可以创建一个中间模块默认导出命名模块
// ManyComponents.js
export const MyComponent = /* ... */;
export const MyUnusedComponent = /* ... */;
// MyComponent.js
export { MyComponent as default } from "./ManyComponents.js";
// MyApp.js
import React, { lazy } from 'react';
const MyComponent = lazy(() => import("./MyComponent.js"));
3、context
1、用途
共享那些对于一个组件树而言是“全局”的数据,例如当前认证的用户、主题或首选语言
2、api
1、React.createContext
2、创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。
3、只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效
2、Context.Provider
1、<MyContext.Provider value={/* 某个值 */}>
2、Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。
3、class.contextType
1、MyClass.contextType = MyContext;
2、使用this.context来获取value值
class MyClass extends React.Component {
static contextType = MyContext;
render() {
let value = this.context;
/* 基于这个值进行渲染工作 */
}
}
4、refs转发
1、forwardref
1、对于渲染原生dom元素的组件,react可以封装实现细节,其他组件不需要获取渲染内部元素的ref,可以减少依赖
2、但是选中元素有时候会很有必要,比如动画,获取非受控组件的值
3、允许某些组件接受ref并向下传递,就是转发给子组件
4、使用forwardref,接受一个箭头函数做参数,箭头函数的参数是props和ref
const 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>;
1、我们通过调用 React.createRef 创建了一个 React ref 并将其赋值给 ref 变量。
2、我们通过指定 ref 为 JSX 属性,将其向下传递给 。
3、React 传递 ref 给 forwardRef 内函数 (props, ref) => …,作为其第二个参数。
4、我们向下转发该 ref 参数到 ,将其指定为 JSX 属性。
5、当 ref 挂载完成,ref.current 将指向 DOM 节点。
2、高阶组件转发ref
5、高阶组件
1、定义
1、是组件复用的技巧
2、是个函数,参数是组件,返回值是新组件
3、组件是将props转化为ui,高阶组件是将组件转化为另一个组件
componentDidMount() {
// ...负责订阅相关的操作...
DataSource.addChangeListener(this.handleChange);
}
componentWillUnmount() {
DataSource.removeChangeListener(this.handleChange);
}
handleChange() {
this.setState({
data: selectData(DataSource, this.props)
});
}
render() {
// ... 并使用新数据渲染被包装的组件!
// 请注意,我们可能还会传递其他属性
return <WrappedComponent data={this.state.data} {...this.props} />;
}
};
}
使用
1、HOC不会修改传入的组件,只是用来将组件包装在容器组件中组成新组件
2、HOC是纯函数,没有副作用
3、包装组件接受容器组件的prop,
4、不应该修改组件,应该组合起来,
6、优化
7、portals
1、Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点
1、用法
1、通常来讲,当你从组件的 render 方法返回一个元素时,该元素将被挂载到 DOM 节点中离其最近的父节点:
2、有时候将子元素插入到 DOM 节点中的不同位置也是有好处的
render() {
// React 并*没有*创建一个新的 div。它只是把子元素渲染到 `domNode` 中。
// `domNode` 是一个可以在任何位置的有效 DOM 节点。
return ReactDOM.createPortal(
this.props.children,
domNode
);
}