前言
- 组件的数据来源有两个地方,分别是属性对象和状态对象
- 属性是父组件传递过来的
- 状态是自己内部维护的,改变状态唯一的方式就是setState
- 属性和状态的变化都会影响视图更新
- 不要直接修改State,构造函数是唯一可以给this.state赋值的地方
类组件状态更新例子
我们现在来实现setState
在Conponent.js里
- 初始化state和更新器
当调用setState时
Updater类
- 保存类Component类实例
- 保存要更新的状态
- 调setState的时候,里面会调Updater的addState方法,将要更新的状态保存起来,然后调emitUpdate发射更新
- emitUpdate里会调updateComponent进行状态更新
- updateComponent会判断当前更新队列里是否要更新,如果有将要更新的数据,则调shouldUpdate
getState方法
- 先拿到老状态,然后循环将要更新的状态队列,新老进行合并,用新状态覆盖老的状态
- 用完之后清空调将要更新的状态队列
- 然后返回新老状态合并后的新状态
- 这个方法在计算新状态
shouldUpdate方法
- 让类组件实例的状态state等于新状态
- 然后调用类组件实例的forceUpdate方法
我们先去react-dom.js里把上次渲染的虚拟dom缓存到组件的实例上
在创建真实DOM的时候,把虚拟DOM和真实DOM进行关联
- 把虚拟DOM生成的真实DOM缓存到虚拟DOM上
findDOM方法
- 从虚拟DOM获取真实DOM
- 真实DOM可能没有,如果没有返回null
- 这个地方有点绕,需要理解,如果虚拟dom上缓存的有真实dom,那么说明这个虚拟dom是一个原生组件,因为只有type是文本或者字符串的时候才会缓存真实dom到虚拟dom上。这个逻辑看上篇文章可以找到答案,在判断type的时候会判断是否是一个函数,如果是一个函数,则继续判断是类组件还是函数组件
- 因为函数组件可能返回的还是组件,可能有很多层, 所以这里需要递归
forceUpdate方法
- 强制更新,更新真实dom
- 拿到老的虚拟dom
- 通过findDom方法去拿到真实dom
- 调用实例的render方法,拿到新的虚拟dom
- 调用compareToVdom进行更新
- 把新虚拟dom成为老的虚拟dom
compareToVdom方法
- parentDOM是组件的父节点
- 找到老的真实dom,创建新的dom
- 把老的真实dom替换为新的真实dom
我们此处只是简单的实现,并没有进行DOM-DIFF,我们后续会进行实现