1.安装React开发调试工具(React Developer Tools):对React项目进行调试
Google -> 更多工具 -> 扩展程序 -> 左下角打开Chrome网上应用店 -> 搜索React -> React Developer Tools -> 添加至Chrome
React Developer Tools调试工具颜色:
-
灰色: 没有用React开发
红色: React项目,线下版本
黑色: React项目,线上版本(相对本地代码有压缩,精悍一点~)
React Developer Tools工具作用:
查看地点:控制栏 -> React菜单
作用一:查看React组件结构
作用二:查看右侧的Props、State等进行调试
PropTypes与DefaultProps
PropTypes:做属性接收的强校验,限制父组件传递给子组件属性的类型
引入PropTypes
import PropTypes from 'prop-types';
使用PropTypes进行校验
import React,{Component} from 'react'; import PropTypes from 'prop-types'; class TodoItem extends Component{ constructor(props) { super(props); this.handleClick = this.handleClick.bind(this);//为了性能考虑,改变函数的this指向通常在constructor中定义 } render(){ const { content,test } = this.props; //结构赋值 return( <div onClick={this.handleClick}> {test} - {content} </div> ) } handleClick(){ const { deleteItem,index } =this.props;//结构赋值 deleteItem(index); } } //对TodoItem组件对类型进行校验 TodoItem.propTypes = { content:PropTypes.oneOfType([PropTypes.string, PropTypes.number]), //表示content属性必须是String类型或Number类型中的一个 deleteItem:PropTypes.func,//表示deleteItem属性必须是function类型 index:PropTypes.number,//表示index属性必须是number类型 test:PropTypes.string.isRequired //isRequired表示test必须要从父组件传递过来,且类型是string类型,如果没传则报出警告 } //如果父组件没有向子组件传递对应的属性,则在这里定义属性的默认值 TodoItem.defaultProps = { test: 'helloworld' } export default TodoItem;
(1)使用
组件名.propTypes
表示对组件属性进行校验(2)使用
属性名:PropTypes.类型
表示属性的类型必须是设定的类型(3)使用
属性名:PropTypes.类型.isRequired
表示属性的类型必须是设定的类型,且必须由父组件传递过来(4)使用
属性名:PropTypes.oneOfType([PropTypes.string,PropTypes.number])
表示属性的类型必须是string或number中的一个(5)…等等验证方式请参见相关文档,如:
PropTypes.instanceOf(object)/PropTyps.oneOf(['News','Photos'])/PropTypes.arrayOf(PropTypes.number)...
如果传值类型与PropTypes不同,则会在控制台给出警告,但对开发并不影响,用来查看对应的相关错误信息。
对于个别属性父类没有传递但在子类却要使用,则使用
组件名.defaultProps={属性名:属性值}
的方式进行设定。【具体可参见上方代码示例】Props,State与render函数(解决数据发生变化,页面就要重新渲染的原理)
render函数在页面初始化的时候会先被执行一次,当state或者props发生变化时,render函数会重新执行,从而重新渲染页面,实现联动
- 当父组件的render函数被执行时,他的子组件的render函数都将被重新执行
2.虚拟DOM
版本一:基本DOM生成流程
- 定义state数据
- 定义JSX模板
- 数据+模板 结合,生成真实的DOM来显示
- 当state发生改变
- 数据+模板 结合,生成真实的DOM,替换原来的DOM
- 缺陷:
- 第一次生成了一个完整的DOM片段
- 第二次生成了一个完整的DOM片段
- 第二次的DOM替换第一次的DOM,非常耗性能
版本二:改良DOM生成流程
- 定义state数据
- 定义JSX模板
- 数据+模板 结合,生成真实的DOM来显示
- 当state发生改变
- 数据+模板 结合,生成真实的DOM,并不直接替换原始的DOM
- 新的DOM(js底层的DocumentFragment)和原始的DOM做比对,找差异
- 找出input框发生的变化
- 只用新的DOM中的input元素,替换掉老的DOM中的input元素
- 缺陷:
- 性能的提升并不明显
版本三:React的虚拟DOM
定义state数据
定义JSX模板
数据+模板 结合,生成虚拟DOM(虚拟DOM就是一个JS对象,用它来描述真实DOM)【js创建js对象损耗很少的性能;但如果js创建jsDOM则有很大的损耗】
Eg.
['div',{id:'abc'},['span',{},'hello world']]
用虚拟DOM的结构,生成真实的DOM来显示
Eg.
<div id="abc"><span>hello world</span></div>
state发生变化
数据+模板 生成新的虚拟DOM(极大的提升了性能)
Eg.
['div',{id:'abc'},['span',{},'bye bye']]
比较原始虚拟DOM和新的虚拟DOM的区别,找到区别是span中的内容(比较虚拟DOM即比较js对象,极大的提升了性能)
直接操作DOM改变span中的内容
优点:
- 减少了对真实DOM的创建与真实DOM的对比
- 利用js对象比较代替DOM比较
3.深入虚拟DOM底层原理
- React生成DOM流程
- JSX => React.createElement => 虚拟DOM(JS对象) => 真实的DOM
return <div>item</div>
等同于return React.createElement('div',{},'item')
。React.createElement是更偏向于底层的接口,提供了一个类似于js对象的内容传递给createElement方法,将该对象变成虚拟DOM,再被转换成真实的DOM。
- 虚拟DOM带来的好处:
- 性能提升了(将DOM比对变成JS对象的比对)
- 使得跨端应用得以实现(React Native)
- 虚拟DOM是JS对象在原生应用和网页应用里都可以被识别
- 利用虚拟DOM转化成原生组件
4. 虚拟DOM中的Diff算法(Difference,原始虚拟DOM与新的虚拟DOM的差异比对的算法)
setState
异步方法,提升React性能
设计成一步函数的初衷:假设连续调用三次setState变更三组数据,时间间隔非常小,React将三次SetState合并成一个SetState,只做成一次虚拟DOM的比对,更新一次DOM,省去性能耗费。
Diff算法
Diff算法 是虚拟DOM进行比对时用到的算法,采用同级比对的概念。
- 比较流程:先比第一层、再比第二层…
- 如果在一层不一致,下面不会继续比,将原始页面的虚拟DOM下面所有虚拟DOM替换
- 优点:
- 同级比较,算法简单从而带来比对的速度快
key值
引入key值的原因:提高虚拟DOM比对的性能