【React】初学高阶指引

A. 无障碍辅助功能

WAI-ARIA是一个为残疾人士等提供无障碍访问动态、可交互Web内容的技术规范。主要针对的是视觉缺陷,失聪,行动不便的残疾人以及假装残疾的测试人员。尤其像盲人,眼睛看不到,其浏览网页则需要借助辅助设备,如屏幕阅读器,屏幕阅读机可以大声朗读或者输出盲文。

在标签内使用aria-*属性【aria属性表】,它描述了元素的属性和状态。
通常与其配合使用的标签是role,它的值表示一个元素的实际意义和作用。

aria-*属性

JSX 支持所有 aria-* HTML 属性。虽然大多数 ReactDOM 变量和属性命名都使用驼峰命名(camelCased),但 aria-* 应该像其在 HTML 中一样使用带连字符的命名法

<input type="text" name="name" value={inputValue}
  aria-label={labelText} aria-required="true"
  onChange={onchangeHandler}  />
A2. 语义化的HTML – React Fragments

语义化的 HTML 是无障碍辅助功能网络应用的基础。 利用多种 HTML 元素来强化您网站中的信息通常可以使您直接获得无障碍辅助功能

有时,语义化的 HTML 会被破坏。比如当在 JSX 中使用 <div> 元素来实现 React 代码功能的时候,又或是在使用列表(<ol><ul><dl>)和 HTML <table> 时。 在这种情况下,我们应该使用 React Fragments 来组合各个组件。
React.Fragment

A3. 无障碍表单

所有的 HTML 表单控制,例如 <input><textarea> ,都需要被标注来实现无障碍辅助功能。我们需要提供屏幕朗读器以解释性标注。

以下资源向我们展示了如何写标注:

尽管这些标准 HTML 实践可以被直接用在 React 中,请注意 for 在 JSX 中应该被写作 htmlFor

<label htmlFor="namedInput">Name:</label>
<input id="namedInput" type="text" name="name"/>

还有很多其他无障碍相关的知识点,本人暂时不准备深入了解无障碍这块相关知识点,所以本文就先不深入学习了。


B. Context

在一个典型的 React 应用中,数据是通过 props 属性自上而下(由父及子)进行传递的,但这种做法对于某些类型的属性而言是极其繁琐的(例如:地区偏好,UI 主题),这些属性是应用程序中许多组件都需要的。Context 提供了一种在组件之间共享此类值的方式,而不必显式地通过组件树的逐层传递 props

context

B.1请谨慎使用 Context

会使得组件的复用性变差。如果你只是想避免层层传递一些属性,组件组合(component composition)有时候是一个比 context 更好的解决方案。

组件组合

B.2 render props

这种模式足够覆盖很多场景了,在这些场景下你需要将子组件和直接关联的父组件解耦。如果子组件需要在渲染前和父组件进行一些交流,你可以进一步使用 render props

<DataProvider render={data => (
  <h1>Hello {data.target}</h1>
)}/>

render渲染子组件,就不需要在主组件中写死。看案例:
render

重要的是要记住,render prop 是因为模式才被称为 render prop ,你不一定要用名为 renderprop 来使用这种模式

render的简写

Render PropsReact.PureComponent(区别于React.Component) 一起使用时要小心

PureComponent

B.3 Context API

Context API

Class.contextType:挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* 基于 MyContext 组件的值进行渲染 */
  }
}
MyClass.contextType = MyContext;

Context.displayNamecontext 对象接受一个名为 displayNameproperty,类型为字符串。React DevTools 使用该字符串来确定 context 要显示的内容:

const MyContext = React.createContext(/* some value */);
MyContext.displayName = 'MyDisplayName';
 // "MyDisplayName.Provider" 在 DevTools 中
<MyContext.Provider>
// "MyDisplayName.Consumer" 在 DevTools 中
<MyContext.Consumer> 
B.4 消费多个 Context
// Theme context,默认的 theme 是 “light” 值
const ThemeContext = React.createContext('light');

// 用户登录 context
const UserContext = React.createContext({
  name: 'Guest',
});

class App extends React.Component {
  render() {
    const {signedInUser, theme} = this.props;

    // 提供初始 context 值的 App 组件
    return (
      <ThemeContext.Provider value={theme}>
        <UserContext.Provider value={signedInUser}>
          <Layout />
        </UserContext.Provider>
      </ThemeContext.Provider>
    );
  }
}

function Layout() {
  return (
    <div>
      <Sidebar />
      <Content />
    </div>
  );
}

// 一个组件可能会消费多个 context
function Content() {
  return (
    <ThemeContext.Consumer>
      {theme => (
        <UserContext.Consumer>
          {user => (
            <ProfilePage user={user} theme={theme} />
          )}
        </UserContext.Consumer>
      )}
    </ThemeContext.Consumer>
  );
}

C. 错误边界

部分UIJavaScript 错误不应该导致整个应用崩溃,为了解决这个问题,React 16 引入了一个新的概念 —— 错误边界。

错误边界

错误边界的工作方式类似于 JavaScript 的 catch {},不过只有React class 组件才可以成为错误边界组件。你可以将它作为一个常规组件去使用:
<ErrorBoundary> <MyWidget /> </ErrorBoundary>

D. Refs转发

image.png

HOC相关转发

非受控组件中也有ref相关内容:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tiATjHyk-1583129974862)(https://upload-images.jianshu.io/upload_images/7108739-27fc170b22398a05.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)]

E. Fragments

最开始A2. 语义化的HTML中已经提到了该知识点:

有时,语义化的 HTML 会被破坏。比如当在 JSX 中使用 <div> 元素来实现 React 代码功能的时候,又或是在使用列表(<ol><ul><dl>)和 HTML <table> 时。 在这种情况下,我们应该使用 React Fragments 来组合各个组件。

React.Fragment

F. 高阶组件HOC

具体而言,高阶组件是参数为组件返回值为新组件的函数。

const EnhancedComponent = 
  higherOrderComponent(WrappedComponent);

HOCReact 的第三方库中很常见,例如 ReduxconnectRelaycreateFragmentContainer

HOC一些相关内容这里就先不展开学习了,就稍微提下一些注意事项

  • 不要在 render 方法中使用 HOC
render() {
  每次调用 render 函数都会创建一个新的 EnhancedComponent
  // EnhancedComponent1 !== EnhancedComponent2
  这将导致子树每次渲染都会进行卸载,和重新挂载的操作!
  const EnhancedComponent = enhance(MyComponent);
  return <EnhancedComponent />;
}

这不仅仅是性能问题 - 重新挂载组件会导致该组件及其所有子组件的状态丢失。

  • 务必复制静态方法
    有时在 React 组件上定义静态方法很有用。例如,Relay 容器暴露了一个静态方法 getFragment 以方便组合 GraphQL 片段。
    当你将 HOC 应用于组件时,原始组件将使用容器组件进行包装。这意味着新组件没有原始组件的任何静态方法
  • Refs 不会被传递
    HOC相关转发

G. Portals

Portal 提供了一种将子节点渲染到存在于父组件以外的 DOM 节点的优秀的方案。

ReactDOM.createPortal(child, container)

第一个参数(child)是任何可渲染的 React 子元素,例如一个元素,字符串或 fragment。第二个参数(container)是一个 DOM 元素。

通常来讲,当你从组件的 render 方法返回一个元素时,
该元素将被挂载到 DOM 节点中离其最近的父节点:

render() {
  // React 挂载了一个新的 div,并且把子元素渲染其中
  return (
    <div>
      {this.props.children}
    </div>
  );
}

然而,有时候将子元素插入到 DOM 节点中的不同位置也是有好处的:

render() {
  // React 并*没有*创建一个新的 div。它只是把子元素渲染到 `domNode` 中。
  // `domNode` 是一个可以在任何位置的有效 DOM 节点。
  return ReactDOM.createPortal(
    this.props.children,
    domNode
  );
}

H. 其他

与第三方库协同、深入JSX、性能优化:这里就先不深入学习了,边用边掌握吧!当然,以上讲的各个知识点都需要通过实践来不断深入理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值