深入JSX
本质上来讲,JSX只是为React.createElement(Component, props, …children)提供的语法糖
指定react的元素类型
- react必须声明
- react可以用点表示法或取,某个组件中的子组件
- 首字母大写,区别html原生标签
- 在运行时选择类型,需要先将类型赋值给大写的变量,不支持表达式形式的标签名
属性- 使用js表达式
- 字符串常量,当传递一个字符串常量时,该值会被解析为HTML非转义字符串。
- 当没有给属性传值时,默认为true
- 扩展属性
JSX子代的表现形式- 字符串常量
- JSX
- js表达式
- 函数
- 布尔,null和undefined都是有效子代,但是不会被渲染
如果你想让类似 false、true、null 或 undefined 出现在输出中,你必须先把它转换成字符串
使用PropTypes进行类型检查
注意: React.PropTypes 自 React v15.5 起已弃用。请使用 prop-types 库代替。
具体参考https://www.reactjscn.com/docs/typechecking-with-proptypes.html
静态类型检查
Flow针对js代码的静态类型检查器。
为了使用 Flow, 你需要:
将 Flow 添加到您的项目作为依赖项。
确保编译后的代码中去除了 Flow 语法。
添加了类型注释并运行 Flow 来检查它们。
在一个项目中添加flow
1
2npm install --save-dev flow-bin
npm run flow init从编译后的代码中剥离Flow
Create React App
如果你的项目是使用 Create React App 建立的,恭喜! Flow 此时已经被默认剥离,所以在这一步你不需要做任何事情。配置Babel
1
npm install --save-dev babel-preset-flow
然后将 flow preset 加入你的 Babel 配置。比如,如果你通过 .babelrc 文件配置 Babel,它可能会如下所示
1 | { |
Flow 不需要 react preset,但他们经常在一起使用。 Flow 本身就理解 JSX 语法。
运行flow
1
npm run flow
添加Flow注释
配置TypeScript的过程差不多,文档很详细https://www.reactjscn.com/docs/static-type-checking.html
Refs和DOM
Refs提供了一种访问在render方法中创建的DOM和react元素的方式
- 在典型数据流外强制修改子组件为react组件的实例
- 在典型数据流外强制修改子组件为DOM元素
何时使用Refs
- 处理焦点,文本选择或媒体控制
- 触发强制动画
- 集成第三方DOM库
不要过度使用Refs,如果可以,状态提升是更适合的做法。
创建Refs- React.createRef()创建refs,通过ref属性获得react元素
访问Refs- 当一个ref属性被传递给一个render函数中的元素,可以使用ref中的current属性对节点引用进行访问
- 当ref属性被用于普通html,React.createRef()将接收底层DOM元素作为它的current属性对节点的引用进行访问
- 当ref属性被用于一个自定义类组件时,ref对象将接收该组件已挂载的实例作为它的current
- 不能在函数式组件上使用ref属性,因为没有实例
为DOM元素添加Ref
undefinedReact会在组件加载时将DOM元素传入current属性,在卸载时则会改为null。ref的更新会发生在componentDidMount或componentDidUpdate生命周期之前。
也可以在函数式组件内部使用ref,只要其指向DOM或者自定义组件
对父组件暴露DOM节点
- 在极少数情况下你可能希望从父组件访问子节点的dom节点
处理的方案有以下几种
- Ref 转发使组件可以像暴露自己的 ref 一样暴露子组件的 ref。
- 将 ref 作为特殊名字的 prop 直接传递。
- findDOMNode(),但是不推荐。
回调Refs
- 函数接受React组件的实例或是HTML DOM元素作为参数,用以存储和被访问
如果 ref 回调以内联函数的方式定义,在更新期间它会被调用两次,第一次参数是 null ,之后参数是 DOM 元素。这是因为在每次渲染中都会创建一个新的函数实例。因此,React 需要清理旧的 ref 并且设置新的。通过将 ref 的回调函数定义成类的绑定函数的方式可以避免上述问题,但是大多数情况下无关紧要。
性能优化
更新UI时,React在内部使用几种巧妙的技术来优化DOM操作数量,对应用来说,使用react不需要做太多的优化工作就可以快速创建用户界面。除此之外,还有一些优化react应用性能的办法。
使用生产版本
使用chrome performance归档组件
- https://building.calibreapp.com/debugging-react-performance-with-react-16-and-chrome-devtools-c90698a522ad
避免重复渲染- React在渲染出的UI内部简历和维护了一个内层的实现方式,它包括了从组建返回的react元素。这一层实现就称为虚拟dom。
当一个组件的props和state改变时,react通过新返回的元素和之前渲染的元素作比较来决定是否更新dom。在某些情况下,可以重写生命周期函数shouldComponentUpdate通过返回false直接跳过比较和渲染阶段从而提升速度。SCU表明了shouldComponentUpdate的返回内容,vDOMEq表明了待渲染的React元素与原始元素是否相等。
如果状态是对象类型,请创建一个新的对象包含变得内容,这样才能保证react可以正确比较和渲染。
另外immutable.js是解决这个问题的另一种方法,它通过结构共享提供不可变的,持久的集合。- 不可突变:一旦创建,集合就不能在另一个时间点改变。
- 持久性:可以使用原始集合和一个突变来创建新的集合。原始集合在新集合创建后仍然可用。
- 结构共享:新集合尽可能多的使用原始集合的结构来创建,以便将复制操作降至最少从而提升性能。