Accessibility可访问性
- WCAG清单概述如下:从Wuhcag WCAG清单 从WebAIM WCAG清单 从A11Y项目清单
- 可以将物品的集合映射到一个数组片段像任何其他类型的元素
- 访问的形式 :每个HTML表单控件,比如<输入>和< >文本区域,需要标明可亲地。我们需要提供描述性的标签也暴露于屏幕阅读器。 如何做到这一点: W3C向我们展示如何标签元素 、WebAIM向我们展示如何标签元素、Paciello组访问名称解释道
- 通知用户的错误 :错误情况需要理解所有用户。如何暴露错误文本屏幕阅读器: W3C演示了用户通知 、WebAIM看着表单验证
- 集中控制 :确保您的web应用程序可以完全操作键盘只有: WebAIM谈到键盘可访问性
- Skiplinks或跳过导航链接是隐藏的导航链接,只有当键盘用户与页面交互变得可见。他们非常容易实现与内部页面锚和一些样式: WebAIM——跳过导航链接
- 注意: 虽然这是一个非常重要的易访问性特征,这也是一个技术应该明智地使用。用它来修复键盘焦点流扰动时,不试图预测用户想要使用的应用程序
- 相同的功能可以通过使用一个适当的事件处理程序,如onBlur和聚焦事件
- 每种类型的部件都有一个特定的设计模式,预计将函数以某种方式由用户和用户代理:wai - aria创作实践,设计模式和小部件 、海登皮克林,咏叹调的例子 、包容的组件
- 设置文档<标题>正确描述当前页面内容,因为这将确保用户仍然意识到当前页面的背景: WCAG——理解文档标题的要求
- 确保所有可读的文本在你的网站上有足够的色彩对比与低视力保持最大限度地由用户可读: WCAG——理解色彩对比的要求 、色彩对比的一切,为什么你应该重新考虑它 、A11yProject -什么是颜色的对比
- 迄今为止最简单也最重要的检查是测试如果你的整个网站可以达到和单独使用键盘。通过: 插入你的鼠标。使用选项卡和Shift +选项卡浏览。使用输入激活元素。在需要时,使用你的键盘箭头键与一些元素,如菜单和下拉
在一些浏览器中我们可以很容易的查看每个元素的可访问性信息的可访问性树: 在Firefox中使用可访问性检查器 、激活可访问性检查员在Chrome 、在OS X Safari中使用可访问性检查器
Code-Splitting代码分割
捆绑很好,但是随着你的应用程序的增长,你的捆绑包也会增长。尤其是如果您包括大型第三方库。你需要注意你包中包含的代码,这样你就不会意外地将其变大,以至于你的应用程序需要很长的时间来加载。
为了避免被一个大包裹缠住,最好先解决问题,然后开始“拆分”你的包裹。代码拆分是webpack和browserify(通过factor bundle)等bundler支持的功能,它可以创建多个bundle,并在运行时动态加载。
代码拆分应用程序可以帮助您“延迟加载”用户当前需要的东西,这可以显著提高应用程序的性能。虽然您没有减少应用程序中的代码总量,但您避免了加载用户可能永远不需要的代码,并减少了初始加载期间所需的代码量。
错误边界
如果另一个模块无法加载(例如,由于网络故障),它将触发一个错误。您可以处理这些错误以显示良好的用户体验,并使用错误边界管理恢复。一旦创建了错误边界,就可以在存在网络错误时,在惰性组件上方的任何位置使用它来显示错误状态。
一个好的起点是路线。Web上的大多数人都习惯于页面转换,需要花费一些时间来加载。您还倾向于一次重新呈现整个页面,这样您的用户就不可能同时与页面上的其他元素交互。
命名出口。react.lazy当前仅支持默认导出。如果要导入的模块使用命名导出,则可以创建一个中间模块,将其作为默认值重新导出。这样可以确保Treeshking继续工作,并且不会拉入未使用的组件context 上下文
请注意:变化的方式确定价值传递对象时,可能会导致一些问题:看到警告
请注意 :反应之前附带一个实验性的上下文API。旧的API将支持在所有16。x版本,但使用它的应用程序应该迁移到新版本。遗留的API将被删除在未来主要反应的版本。读遗留环境文档error bound误差界限/错误边界
误差界限呈现期间捕获错误,在生命周期方法,在构造函数的整棵树。
请注意:错误边界不捕获错误: 事件处理程序(了解更多)、 异步代码(例如setTimeout或requestAnimationFrame回调)、 服务器端呈现、错误抛出错误边界本身(而不是它的孩子)
super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。 加与不加props的区别究竟在哪里呢?:需要在构造函数内使用this.props
异常处理
/*在 React 15.x 及之前的版本中,组件内的异常有可能会影响到 React 的内部状态,进而导致下一轮渲染时出现未知错误。这些组件内的异常往往也是由应用代码本身抛出,在之前版本的 React更多的是交托给了开发者处理,而没有提供较好地组件内优雅处理这些异常的方式。在 React 16.x 版本中,引入了所谓 Error Boundary 的概念,从而保证了发生在 UI 层的错误不会连锁导致整个应用程序崩溃;未被任何异常边界捕获的异常可能会导致整个 React 组件树被卸载。所谓的异常边界即指某个能够捕获它的子元素(包括嵌套子元素等)抛出的异常,并且根据用户配置进行优雅降级地显示而不是导致整个组件树崩溃。异常边界能够捕获渲染函数、生命周期回调以及整个组件树的构造函数中抛出的异常。我们可以通过为某个组件添加新的 componentDidCatch(error, info) 生命周期回调来使其变为异常边界*/class ErrorBoundary extends React.Component {constructor(props) {super(props);this.state = { error: null, errorInfo: null };}componentDidCatch(error, errorInfo) {// Catch errors in any components below and re-render with error messagethis.setState({error: error,errorInfo: errorInfo})// You can also log error messages to an error reporting service here}render() {if (this.state.errorInfo) {// Error pathreturn (<div><h2>Something went wrong.</h2><details style={{whiteSpace: 'pre-wrap' }}>{this.state.error && this.state.error.toString()}<br />{this.state.errorInfo.componentStack}</details></div>);}// Normally, just render childrenreturn this.props.children;} }/*然后我们就可以如常使用该组件:<ErrorBoundary><MyWidget /></ErrorBoundary>*//*componentDidCatch() 方法就好像针对组件的 catch {} 代码块;不过 JavaScript 中的try/catch 模式更多的是面向命令式代码,而 React 组件本身是声明式模式,因此更适合采用指定渲染对象的模式。需要注意的是仅有类组件可以成为异常边界,在真实的应与开发中我们往往会声明单个异常边界然后在所有可能抛出异常的组件中使用它。另外值得一提的是异常边界并不能捕获其本身的异常,如果异常边界组件本身抛出了异常,那么会冒泡传递到上一层最近的异常边界中。*/class BuggyCounter extends React.Component {constructor(props) {super(props);this.state = { counter: 0 };this.handleClick = this.handleClick.bind(this);}handleClick() {this.setState(({counter}) => ({counter: counter + 1}));}render() {if (this.state.counter === 5) { // Simulate a JS errorthrow new Error('I crashed!');}return <h1 onClick={this.handleClick}>{this.state.counter}</h1>;}}function App() {return (<div><p><b> This is an example of error boundaries in React 16.<br /><br />Click on the numbers to increase the counters.<br />The counter isprogrammed to throw when it reaches 5. This simulates a JavaScript error ina component.</b></p><hr /> <ErrorBoundary><p>These two counters areinside the same error boundary. If one crashes, the error boundary willreplace both of them.</p><BuggyCounter /><BuggyCounter /></ErrorBoundary><hr /><p>These two counters are each inside of their own error boundary.So if one crashes, the other is not affected.</p><ErrorBoundary><BuggyCounter /></ErrorBoundary><ErrorBoundary><BuggyCounter /></ErrorBoundary></div>);}ReactDOM.render(<App />,document.getElementById('root'));
添加错误边界让你出现问题时提供更好的用户体验。例如: Facebook Message包裹栏的内容,信息面板中,谈话记录,信息输入到单独的边界。如果这些 UI 组件在一个区域崩溃,其他人保持互动。鼓励使用 JS 错误报告服务/构建自己的,这样就可以了解未处理的异常发生在生产,并修复 他们。
请注意:组件名称显示在堆栈跟踪依赖Function.name属性。如果支持老式浏览器和设备可能没有提供这个本地(考虑包括Function.name polyfill在打包应用程序,比如function.name-polyfill。或者,可以显式地设置displayName属性你所有的组件。
Forwarding Refs Ref进入(技术)
FancyButton通常不需获得一个Ref DOM元素内部的按钮。是好的,因为它可以防止组件依赖彼此的DOM结构太多。
使用FancyButton这样,组件可以ref底层按钮DOM节点并访问它如果必要喜欢如果他们直接使用DOM按钮。这是一个循序渐进的解释发生了什么在上面的例子中: (1)我们创建一个反应ref通过调用反应。createRef,并将其分配给一个参考变量。(2)我们通过我们的裁判< FancyButton ref = { ref } >通过指定它作为JSX属性。(3)反应经过裁判(道具、ref)= >……forwardRef内部函数作为第二个参数。(4)我们提出这个 Ref 争论到<按钮ref = { ref } >通过指定它作为JSX属性。(4)当 Ref, ref.current将指向<按钮> DOM节点
请注意 :第二 Ref 争论只有当你定义一个组件存在的反应。forwardRef电话。常规函数或类组件不接受 Ref 争论,和 Ref 也不是可用的道具。 Ref转发并不局限于DOM组件。你也可以参转发给类组件实例
Flagments 片段
关键片段
用显式的
关键是唯一的属性可以通过片段。在未来,我们可能会增加支持额外的属性,比如事件处理程序
function Glossary(props) {return (<dl>{props.items.map(item => (// Without the `key`, React will fire a key warn<React.Fragment key={item.id}><dt>{item.term}</dt><dd>{item.description}</dd></React.Fragment>))}</dl>);}
Higher-Order Components 高阶组件
具体地说,一个高阶组件是一个函数,把一个组件并返回一个新的组件
- CommentList和BlogPost并不相同,他们在数据源调用不同的方法,他们呈现不同的输出。但他们大部分的实现是一样的: 安装,改变监听器添加到数据源。在侦听器、呼叫设置状态只要数据源发生变化。在卸载、删除更改侦听器
hoc不会修改输入组件,也不会使用继承来复制其行为。相反,hoc通过将原始组件包装在容器组件中来组合它。hoc是一个零副作用的纯函数。
就这样!被包装的组件接收容器的所有属性,以及一个新的属性数据,用于呈现其输出。hoc与数据的使用方式 和使用原因无关,而封装组件与数据的来源无关。<br /> 因为withsubscription是一个普通函数,所以您可以添加任意多个或任意少的参数。例如,您可能希望使数据 属性的名称可配置,以进一步将hoc与包装的组件隔离开来。或者您可以接受配置shouldComponentUpdate 的参数,或者接受配置数据源的参数。这些都是可能的,因为hoc可以完全控制如何定义组件。<br /> 与组件一样,withsubscription和封装组件之间的契约完全基于props。这使得将一个hoc替换为另一个hoc变 得容易,只要它们为被包装的组件提供相同的属性。例如,如果更改数据提取库,这可能很有用
有一些问题。一种是输入组件不能与增强组件分开重用。更重要的是,如果您将另一个hoc应用于同时改变componentwillreceiveprops的增强组件,那么第一个hoc的功能将被覆盖!这个hoc也不能用于没有生命周期方法的功能组件。
变异的hoc是一个泄漏的抽象,消费者必须知道它们是如何实现的,以避免与其他hoc发生冲突。
而不是突变,hocs应该使用组合,将输入组件包装在容器组件中function logProps(WrappedComponent) {return class extends React.Component {componentWillReceiveProps(nextProps) {console.log('Current props: ', this.props);console.log('Next props: ', nextProps);}render() {// Wraps the input component in a container, without mutating it. Good!return <WrappedComponent {...this.props} />;}}}
连接是一个高阶函数,返回一个高阶组件! 这似乎令人困惑或不必要的形式,但它有一个有用的属性。单参数的像一个连接返回的函数签名组件= >组件。函数的输出类型是一样的输入类型很容易组合在一起
这里的问题不仅仅是性能问题——重新安装组件会导致该组件及其所有子组件的状态丢失。
相反,在组件定义之外应用hocs,以便生成的组件只创建一次。然后,它的身份将在渲染中保持一致。不管怎 样,这通常是你想要的。
在那些需要动态应用hoc的罕见情况下,您也可以在组件的生命周期方法或其构造函数内进行。
静态方法必须复制到
有时在一个反应组件上定义一个静态方法是有用的。例如,中继容器公开了一个静态方法getfragment,以便于 组成graphql片段。
但是,将hoc应用于组件时,原始组件将被容器组件包装。这意味着新组件没有原始组件的任何静态方法。
引用未通过虽然高阶组件的约定是将所有属性传递给封装的组件,但这对refs不起作用。这是因为裁判不是真正的道具钥匙,而是由react专门处理的。如果向其组件是hoc结果的元素添加引用,则引用的是最外层容器组件的实例,而不是包装组件。
此问题的解决方案是使用react.forwardRef API
