vue与react的异同
相同
- 使用vdom提高重绘性能
- 提供了响应式 (Reactive) 和组件化 (Composable) 的视图组件。
- 将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。
不同
vue | react | |
---|---|---|
设计思想 | 可变数据 | 数据不可变 |
编写语法 | 模板(声明式) | jsx(编程式) |
数据流 | 数据双向绑定 | 单项数据流 |
数据监听 | getter/setter | 比较引用 |
逻辑复用 | mixins | HOC |
构建工具 | vue-cli | create-react-app |
跨平台 | react native | weex |
生命周期 | —————初始化(4)—— beforeCreate created beforeMount mounted —————-运行(2)—- beforeUpdate updated —————-销毁(2)—- beforeDestory destroyed |
—————初始化(5)——— getDefalutProps getInitialState componentWillMount render componentDidMount —————-运行(5)———— componentWillReceiveProps shouldComponentUpdate componentWillUpdate componentDidUpdate ——————销毁(1)————- componentDidMount |
销毁 | beforeDestroy+destroyed | componentWillUnmount |
状态管理 | vuex | redux |
diff算法 | 双端比较 |
vue/react的dom diff过程,二者有什么差异
对比树, 未优化的复杂度是O(n^3), 优化之后是O(n)
删除BC节点, 插入K, 改变AG的位置
['A', 'B', 'C', 'D', 'E', 'F', 'G']
['D', 'A', 'G', 'F', 'K', 'E']
vue, snabbdom
首尾两个指针,双向遍历, 加速遍历速度
循环
- 寻找相同
- 两首对比。向后移动
- 两位对比。向前移动
- 旧首、新尾对比。移动首部到尾部, 向中间移动
- 旧尾、新首对比。移动尾部到首部, 向中间移动
- 当前新首是否存在于旧集合
- 存在。移动
- 不存在。插入
- 对比新旧集合长度, 添加、删除
if (sameVnode(oldStartVnode, newStartVnode)) {
patchVnode(oldStartVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)
oldStartVnode = oldCh[++oldStartIdx]
newStartVnode = newCh[++newStartIdx]
}
else if (sameVnode(oldEndVnode, newEndVnode)) {
patchVnode(oldEndVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx)
oldEndVnode = oldCh[--oldEndIdx]
newEndVnode = newCh[--newEndIdx]
}
else if (sameVnode(oldStartVnode, newEndVnode)) { // Vnode moved right
patchVnode(oldStartVnode, newEndVnode, insertedVnodeQueue, newCh, newEndIdx)
canMove && nodeOps.insertBefore(parentElm, oldStartVnode.elm, nodeOps.nextSibling(oldEndVnode.elm))
oldStartVnode = oldCh[++oldStartIdx]
newEndVnode = newCh[--newEndIdx]
}
else if (sameVnode(oldEndVnode, newStartVnode)) {
patchVnode(oldEndVnode, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)
canMove && nodeOps.insertBefore(parentElm, oldEndVnode.elm, oldStartVnode.elm)
oldEndVnode = oldCh[--oldEndIdx]
newStartVnode = newCh[++newStartIdx]
}
else {// 没有找到相同的可以复用的节点,则新建节点处理
/* 生成一个key与旧VNode的key对应的哈希表(只有第一次进来undefined的时候会生成,也为后面检测重复的key值做铺垫) 比如childre是这样的 [{xx: xx, key: 'key0'}, {xx: xx, key: 'key1'}, {xx: xx, key: 'key2'}] beginIdx = 0 endIdx = 2 结果生成{key0: 0, key1: 1, key2: 2} */
if (isUndef(oldKeyToIdx)) oldKeyToIdx = createKeyToOldIdx(oldCh, oldStartIdx, oldEndIdx)
/*如果newStartVnode新的VNode节点存在key并且这个key在oldVnode中能找到则返回这个节点的idxInOld(即第几个节点,下标)*/
idxInOld = isDef(newStartVnode.key)
? oldKeyToIdx[newStartVnode.key]
: findIdxInOld(newStartVnode, oldCh, oldStartIdx, oldEndIdx)
if (isUndef(idxInOld)) { // New element
/*newStartVnode没有key或者是该key没有在老节点中找到则创建一个新的节点*/
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
} else {
/*获取同key的老节点*/
vnodeToMove = oldCh[idxInOld]
if (sameVnode(vnodeToMove, newStartVnode)) {
/*如果新VNode与得到的有相同key的节点是同一个VNode则进行patchVnode*/
patchVnode(vnodeToMove, newStartVnode, insertedVnodeQueue, newCh, newStartIdx)
//因为已经patchVnode进去了,所以将这个老节点赋值undefined
oldCh[idxInOld] = undefined
/*当有标识位canMove实可以直接插入oldStartVnode对应的真实Dom节点前面*/
canMove && nodeOps.insertBefore(parentElm, vnodeToMove.elm, oldStartVnode.elm)
} else {
// same key but different element. treat as new element
/*当新的VNode与找到的同样key的VNode不是sameVNode的时候(比如说tag不一样或者是有不一样type的input标签),创建一个新的节点*/
createElm(newStartVnode, insertedVnodeQueue, parentElm, oldStartVnode.elm, false, newCh, newStartIdx)
}
}
newStartVnode = newCh[++newStartIdx]
}
react
同层三种操作:插入、移动、删除
同一层级的同组子节点,添加唯一 key 进行区分
- 遍历新集合。 判断元素是否存在于旧集合
- 不存在, 则插入
- 存在。判断当前位置和之前的位置
- 当前位置>旧位置, 移动
- 遍历旧集合。判断旧元素是否在于新集合
- 找不到, 移除旧元素
```
function patch(newArr, oldArr) {
for(let i=0; i
oldIndex) {
} } else { // append } } for(let i=0; i<oldArr.length; i++) { let cur = oldArr[i]; if (!newArr.includes(cur)) { // remove } } }// move
- 找不到, 移除旧元素
```
function patch(newArr, oldArr) {
for(let i=0; i
patch(new, old) ``` http://hcysun.me/vue-design/zh/renderer-diff.html#%E5%8F%8C%E7%AB%AF%E6%AF%94%E8%BE%83%E7%9A%84%E5%8E%9F%E7%90%86
vue/react开发与jQuery开发有什么区别
React16中使用了 Fiber,但是 Vue 是没有 Fiber 的,为什么呢?
原因是二者的优化思路不一样:
- Vue 是基于 template 和 watcher 的组件级更新,把每个更新任务分割得足够小,不需要使用到 Fiber 架构,将任务进行更细粒度的拆分
- React 是不管在哪里调用 setState,都是从根节点开始更新的,更新任务还是很大,需要使用到 Fiber 将大任务分割为多个小任务,可以中断和恢复,不阻塞主进程执行高优先级的任务