一.React框架
1 .官网网址:https://react.docschina.org/
React 是一个用于构建用户界面的JavaScript库
核心专注于视图,目的实现组件化开发
每个引入的组件里有什么东西
react是核心模块,里面有创建组件,属性和状态的管理
react-dom把虚拟dom转变为真实dom
2.REACT是MVC框架
m: model 数据层 v: view 视图层 c: controll 控制层
3.JSX语法的基础使用
JSX语法:javascript xml(html);在react中支持jsx语法,后缀名是jsx的文件,那么可以在这个文件中直接写标签(这个标签不能被浏览器识别,是虚拟dom),那么这个标签就代表了一个react元素,当真正编译这个标签时,其实是一个react元素对象(react元素,将虚拟的DOM对象转成真实的DOM)
每一个组件的视图只能有一个根元素节点(react元素必须只能有一个根元素)
只要在JS中使用JSX,就必须引入react(因为需要用到create-element)
在react工程化项目中(vscode),我们会把需要写react组件的JS命名为.jsx这样只有一个目的:让创建的文件识别jsx语法,而在create-react-app脚手架创建的项目中,已经包含了对.jsx文件的处理
• ReactDOM.render(),第一个参数为react元素对象,第二个参数为一个元素容器(不建议是html或者body,指定一个元素容器#root)第三个参数为一个函数,当把虚拟dom渲染到浏览器页面中后会执行这个函数。例子:ReactDOM.render(<div></div>,document.querySelector("#root"),function(){})
• ReactDOM是一个对象,里面包含render这个方法,render这个方法是将react元素转成真实的dom元素,并把这个真实的dom元素插入到页面的根元素中
• 在ReactDOM.render处理的时候,如果发现第一个参(type属性)不是标签字符串,而是一个函数的(一个类),与此同时会把函数执行(创建类的一个实例),于此同时会把调用组件的时候,设置的行内属性传递给这个函数或者这个类
• 只能有一个render函数将虚拟dom元素通过reactDOM.render渲染到根元素root中,如果有多个,那么后面的会把前面的覆盖;如果是挂载到不同的元素是可以的;如果挂载到同一个元素下,后面的将会把前面的覆盖
• 当执行render时,会把根元素中的所有的元素进行替换
• 当把react元素挂载到页面之后才可以获取
• ReactDOM.render是同步渲染dom,当真正挂载完以后才会继续执行下面的代码
• JSX语法中基于{}绑定动态数据值或者JS表达式,取得的是当前作用域下的值
• null和undefined代表空对象,布尔值也为空对象
• 大括号中支持三元运算符以及表达式
• 在括号中不能直接使用对象或者函数(但是可以用函数执行)
• 括号中可以直接放入数组,数组的每一项可以是react元素,最后会被一起渲染到页面上
• 行间属性不能直接使用class关键字,在react中有特殊含义(要想起class名用className)
• 在react元素中label标签使用for属性时,要把for换成htmlFor(这个for属性值的意思是选中与之绑定的input框,得呵input框的id值相同)
• 给JSX元素设置样式
• 设置行内样式时style不能是字符串,必须是一个对象(需要用{{}}包起来),如果样式中有'-',需要将其样式转成驼峰的方式,如:margin-right => marginRight
二.虚拟DOM
1.什么是虚拟DOM
虚拟DOM是真实DOM在内存中的表示。UI的表现形式保存在内存中,并与实际的DOM同步。这是一个发生在渲染函数调用和元素在屏幕上显示之间的步骤,整个过程被称为调和
2.为什么虚拟DOM能提高性能
• 虚拟dom相当于在js和真实dom之间加了一个缓存,利用了dom-diff算法避免了一些不必要的dom操作,从而提高性能
• 具体步骤如下:
a. 用javascript对象结构表示dom树的结构,然后用这个树构建一个真正的dom树,插到文档当中
b. 当状态变更的时候,重新构造一棵新的dom树,然后用新的树和旧的树作比较,记录两棵树的差异
c. 把记录的差异应用到步骤一所构建的真实的dom树上,视图就更新了
d. 把树形结构按照层级分解,只比较同级属性
3.diff算法
• 给列表结构的每个单位添加唯一的key属性,方便比较
• React只会匹配相同class的component(此处的class指class名)
• 合并操作,调用component的setstate方法的时候,React将其标记为dirty,到每一个事件循环结束,React检查所有标记dirty的component重新绘制,
• 选择性子树渲染。开发人员可以重写shouldComponentupdate提高diff的性能
4.从虚拟dom(JSX)到真实dom的渲染原理
1. 把JSX基于Babel-Preset-React-App语法解析包变为create-elelment格式
a. 每当遇到一个标签都会create-element
b. react.create-element([标签名],[props|null],...)有几个子节点,从第三个实参开始分别是每一个子节点的处理(文本节点直接就是文本内容,元素节点还需要再一次create-element处理)
2. 执行create-element
a. 返回一个对象{$$typeof: Symbol(react.element),key: null,ref: null,type: "span",props: {className: "a", children: "222"}}
ⅰ. type:标签名/组件
ⅱ. peops:是一个对象,里面有给元素标签上设置的属性(REF/KEY除外),没有子节点则没有children选项,有子节点才有children,只有一个字节点它的值是单个值,如果有多个子节点,它的值是一个数组
3. 基于ReactDOM.render把生成的对象变成真实的dom,最后渲染到浏览器页面的指定容器中
三.react的createElement(创建虚拟dom)
1.React.createElement 创建虚拟dom,第一个参为标签类型,第二个参为行间属性,第三个参为文本内容,第四个参为子节点(子节点可以无限嵌套)
2.当js解析时,会把这个标签通过React.createElement转成真实的DOM
3.执行顺序为先把最里面的create-element执行,执行完依次执行外层的
4.JSX语法其实是React.createElement的语法糖;
四.React的数据绑定
1.JSX要求循环绑定的元素都要设置一个属性key,存储的值是当前循环中的唯一值(key是dom diff时候的重要凭证,key值一般不要设置为循环的索引,而是设置为某一个具体不变的值)
2.在react中的数据绑定,需要使用数组的map方法,将数据一一映射成一个react元素
React的事件对象
• React中的事件是合成事件
• 底层源码上是基于事件委托把所有的事件进行代理的(跨平台)