深入JSX,首先知道JSX是React.createElement(component, props, ...children)的语法糖。
1 在JSX文件中可以使用.表达式
在jsx中,也可以使用.表达式来引入React组件,如果你在一个类型中声明了很多React组件,这样做会很方便引用,同时也避免命名的冲突。
const Common = {
CardComponent(props){
return <div>Card</div>
}
}
function CardList(){
return <Common.CardComponent color='red' />
}
2 运行时选择组件类型
在开发复杂业务时经常会碰到需要在运行时选择组件类型,比如通过prop
来决定渲染哪个组件,要实现这样的功能需要注意,必须先要把它赋值给一个大写变量。
import { Notice, Activity,HomeWork } from './CardStyle';
const components = {
notice: Notice,
activity: Activity
};
function CardList(props) {
// JSX 类型组件首字母必须大写
const Specific = components[props.cardType];
return <Specific story={props.data} />;
}
3 传递函数作为后代
通常在JSX中的js表达式会被当做字符串,React元素或者js变量。但是,可以利用props.children把任何数据传递给子组件。例如:
function CardList(props) {
return <div>{
props.list.map((i)=>
props.children(i)
)
}</div>;
}
function Card() {
return (
<CardList numTimes={10}>
{(item) => <div key={item.index}>This is item {item.val} in the list</div>}
</CardList>
);
}
这种用法可以减少代码量,也比较少见到 -.-
4. 善于使用Context
Context 通过组件树提供了一个传递数据的方法,从而避免了在每一个层级手动的传递 props 属性。简单说就是,当你不想在组件树中通过逐层传递props或者state的方式来传递数据时,可以使用Context来实现跨层级的组件数据传递。
//Card.jsx
import React, { createContext } from 'react'
export default const ThemeContext = createContext('ReactContext');
function card() {
return (
<ThemeContext.Provider value={themes.dark}>
<Toolbar />
</ThemeContext.Provider>
);
}
//Toolbar.jsx
import ThemedButton from './ThemedButton';
function Toolbar(props) {
return (
<div>
<ThemedButton />
</div>
);
}
//ThemedButton.jsx
import React, { useContext } from 'react'
import ThemeContext from './Card';
function ThemedButton() {
const theme = useContext(ThemeContext);
return (
<button style={{ background: theme.background, color: theme.foreground }}>
{theme}
</button>
);
}
注意:useContext(MyContext) 只是让你能够读取 context 的值以及订阅 context 的变化。你仍然需要在上层组件树中使用 <MyContext.Provider> 来为下层组件提供 context。另外,即使祖先使用 React.memo 或 shouldComponentUpdate,也会在组件本身使用 useContext 时重新渲染。
结合useReducer, 在一定程度甚至可以代替React-redux。
5. 异常捕获边界(Error)
如果模块加载失败(如网络问题),它会触发一个错误。你可以通过异常捕获边界(Error boundaries)技术来处理这些情况,以显示良好的用户体验并管理恢复事宜。 下面例子中,MyErrorBoundary组件在 react.docschina.org/docs/error-…
import MyErrorBoundary from './MyErrorBoundary';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
const MyComponent = () => (
<MyErrorBoundary>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</MyErrorBoundary>
);
如果在 MyComponent 渲染完成后,包含 OtherComponent 的模块还没有被加载完成,我们可以使用加载指示器为此组件做优雅降级。这里我们使用 Suspense 组件来解决
6 性能优化
在内部,React使用几种巧妙的技术来最小化更新UI所需的昂贵的DOM操作的数量。对于许多应用程序,使用React将导致快速的用户界面,而无需进行大量工作来专门优化性能。不过,有几种方法可以加快React应用程序的速度。
通过安装React Developer Tools for Chrome 可以进行app的检查和极致优化。比如通过TimeLine
查看代码的运行时间等。
官网地址:reactjs.org/docs/optimi…
最常见也是最终要的性能优化就是避免视图重复刷新
影响网页性能最大的因素是浏览器的重排(repaint)和重绘(reflow)。React的Virtual DOM就是尽可能地减少浏览器的重排和重绘。 从React渲染过程来看,如何防止不必要的渲染是解决问题的关键。
-
拆分组件为子组件,对组件做更细粒度的控制。保持纯净状态,可以让方法或组件更加专注(focus),体积更小(small),更独立(independent),更具有复用性(reusability)和可测试性(testability)。
这里有一个重要概念就是纯函数。纯函数非常方便进行方法级别的测试及重构,它可以让程序具有良好的扩展性及适应性。纯函数是函数式开发的基础。React组件本身就是纯函数,即传入指定props得到一定的Virtual DOM,整个过程都是可预测的。
-
使用react Hooks和自定义Hooks 例如将依赖传入
useMemo,useCallback
第二个参数,来避免依赖未改变带来的重复渲染。 -
懒加载 使用react新增api
react.lazy
来做组件的懒加载,提高用户体验。
import React, { Suspense } from 'react';
const OtherComponent = React.lazy(() => import('./OtherComponent'));
function MyComponent() {
return (
<div>
<Suspense fallback={<div>Loading...</div>}>
<OtherComponent />
</Suspense>
</div>
);
}
像渲染常规组件一样处理动态引入(的组件)。
这个代码将会在渲染组件时,自动导入包含 OtherComponent 组件的包。React.lazy 接受一个函数,这个函数需要动态调用 import()。它必须返回一个 Promise,该 Promise 需要 resolve 一个 defalut export 的 React 组件。
然后应在 Suspense 组件中渲染 lazy 组件,如此使得我们可以使用在等待加载 lazy 组件时做优雅降级(如 loading 指示器等)。
另外,也可以在打包方面做webpack的动态加载:传送门
- 运用immutablejs JavaScript中对象一般是可变的,因为使用引用赋值,新的对象的改变将影响原始对象。为了解决这个问题是使用深拷贝或者浅拷贝,但这样做又造成了CPU和内存的浪费。Immutable data很好地解决了这个问题。
Immutable data就是一旦创建,就不能再更改的数据。对Immutable对象进行修改、添加或删除操作,都会返回一个新的Immutable对象。Immutable实现的原理是持久化的数据结构。即使用旧数据创建新数据时,保证新旧数据同时可用且不变。同时为了避免深拷贝带来的性能损耗,Immutable使用了结构共享(structural sharing),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其他节点则进行共享。
以上内容都是在业务开发中遇到学习的,合理的运用技巧一方面可以提高开发效率,另一方面也可以使得代码整洁,结构清晰,有更好的建议或意见欢迎点赞留言评论,本文持续更新... 下期分享
你不知道的硬核数据状态管理
,欢迎关注~