mysql 无论输入什么都是现实 not found_NotAPanda

本文详细对比了Vue和React的源码实现,包括挂载过程、依赖收集与监听、diff和patch算法。Vue中数据变更通过`setter`触发依赖更新,而React在`setState`后组件自行处理。Vue的`diff`使用双向遍历,React则使用首位不动的策略。此外,文章还讨论了Vue中`data`必须为函数的原因,以及React的`state`对象。
摘要由CSDN通过智能技术生成

activities?page=1

前言

面试竞争力越来越大,是时候撸一波Vue和React源码啦;

本文从20个层面来对比Vue和React的源码区别;

如果需要了解API的区别,请戳:

Vue 开发必须知道的 36 个技巧

React 开发必须知道的 34 个技巧

文章源码:请戳,原创码字不易,欢迎star!

1.Vue和React源码区别

1.1 Vue源码

来张Vue源码编译过程图

activities?page=1

图片来源:分析Vue源码实现

1.1.1 挂载

初始化$mounted会挂载组件,不存在 render 函数时需要编译(compile);

1.1.2 compile

1.compile 分为 parse,optimize 和 generate,最终得到 render 函数;

2.parse 调用 parseHtml 方法,方法核心是利用正则解析 template 的指令,class 和 stype,得到 AST;

3.optimize 作用标记 static 静态节点,后面 patch,diff会跳过静态节点;

4.generate 是将 AST 转化为 render 函数表达式,执行 vm._render 方法将 render 表达式转化为VNode,得到 render 和 staticRenderFns 字符串;

5.vm._render 方法调用了 VNode 创建的方法createElement// render函数表达式

(function() {

with(this){

return _c('div',{ //创建一个 div 元素

attrs:{"id":"app"} //div 添加属性 id

},[

_m(0), //静态节点 header,此处对应 staticRenderFns 数组索引为 0 的 render function

_v(" "), //空的文本节点

(message) //判断 message 是否存在

//如果存在,创建 p 元素,元素里面有文本,值为 toString(message)

?_c('p',[_v("\n "+_s(message)+"\n ")])

//如果不存在,创建 p 元素,元素里面有文本,值为 No message.

:_c('p',[_v("\n No message.\n ")])

]

)

}

})

1.1.3 依赖收集与监听

这部分是数据响应式系统

1.调用 observer(),作用是遍历对象属性进行双向绑定;

2.在 observer 过程中会注册Object.defineProperty的 get 方法进行依赖收集,依赖收集是将Watcher 对象的实例放入 Dep 中;

3.Object.defineProperty的 set 会调用Dep 对象的 notify 方法通知它内部所有的 Watcher 对象调用对应的 update()进行视图更新;

4.本质是发布者订阅模式的应用

1.1.4 diff 和 patch

diff 算法对比差异和调用 update更新视图:

1.patch 的 differ 是将同层的树节点进行比较,通过唯一的 key 进行区分,时间复杂度只有 O(n);

2.上面将到 set 被触发会调用 watcher 的 update()修改视图;

3.update 方法里面调用 patch()得到同级的 VNode 变化;

4.update 方法里面调用createElm通过虚拟节点创建真实的 DOM 并插入到它的父节点中;

5.createElm实质是遍历虚拟 dom,逆向解析成真实 dom;

1.2 React 源码

来张React源码编译过程图

activities?page=1

图片来源:React源码解析

1.2.1 React.Component

1.原型上挂载了setState和forceUpdate方法;

2.提供props,context,refs 等属性;

3.组件定义通过 extends 关键字继承 Component;

1.2.2 挂载

1.render 方法调用了React.createElement方法(实际是ReactElement方法);

2.ReactDOM.render(component,mountNode)的形式对自定义组件/原生DOM/字符串进行挂载;

3.调用了内部的ReactMount.render,进而执行ReactMount._renderSubtreeIntoContainer,就是将子DOM插入容器;

4.ReactDOM.render()根据传入不同参数会创建四大类组件,返回一个 VNode;

5.四大类组件封装的过程中,调用了mountComponet方法,触发生命周期,解析出 HTML;

1.2.3 组件类型和生命周期

1.ReactEmptyComponent,ReactTextComponent,ReactDOMComponent组件没有触发生命周期;

2.ReactCompositeComponent类型调用mountComponent方法,会触发生命周期,处理 state 执行componentWillMount钩子,执行 render,获得 html,执行componentDidMounted

1.2.4 data 更新 setState

细节请见 3.1

1.2.5 数据绑定

1.setState 更新 data 后,shouldComponentUpdate为 true会生成 VNode,为 false 会结束;

2.VNode会调用 DOM diff,为 true 更新组件;

1.3 对比

React:

1.单向数据流;

2.setSate 更新data 值后,组件自己处理;

3.differ 是首位是除删除外是固定不动的,然后依次遍历对比;

Vue:

1.v-model 可以实现双向数据流,但只是v-bind:value 和 v-on:input的语法糖;

2.通过 this 改变值,会触发 Object.defineProperty的 set,将依赖放入队列,下一个事件循环开始时执行更新时才会进行必要的DOM更新,是外部监听处理更新;

3.differcompile 阶段的optimize标记了static 点,可以减少 differ 次数,而且是采用双向遍历方法;

2.React 和 Vue 渲染过程区别

2.1 React

1.生成期(挂载):参照 1.2.1

2.更新: 参照1.1.3和 1.1.4

3.卸载:销毁挂载的组件

2.2 Vue

1.new Vue()初始化后initLifecycle(vm),initEvents(vm),initRender(vm),callHook(vm,beforeCreate),initState(vm),callHook(vm,created);A.initLifecycle, 建立父子组件关系,在当前实例上添加一些属性和生命周期标识。如:children、refs、_isMounted等;

B.initEvents,用来存放除@hook:生命周期钩子名称="绑定的函数"事件的对象。如:$on、$emit等;

C.initRender,用于初始化$slots、$attrs、$listeners;

D.initState,是很多选项初始化的汇总,包括:props、methods、data、computed 和 watch 等;

E.callHook(vm,created)后才挂载实例

2.compileToFunction:就是将 template 编译成 render 函数;

3.watcher: 就是执行1.2.3;

4.patch:就是执行 1.2.4

3.AST 和 VNode 的异同

1.都是 JSON 对象;

2.AST 是HTML,JS,Java或其他语言的语法的映射对象,VNode 只是 DOM 的映射对象,AST 范围更广;

3.AST的每层的element,包含自身节点的信息(tag,attr等),同时parent,children分别指向其父element和子element,层层嵌套,形成一棵树

  • itemid:{ {item.id}}

//转化为 AST 格式为

{

"type": 1,

"tag": "div",

"attrsList": [

{

"name": "id",

"value": "app"

}

],

"attrsMap": {

"id": "app"

},

"children": [

{

"type": 1,

"tag": "ul",

"attrsList": [],

"attrsMap": {},

"parent": {

"$ref": "$"

},

"children": [

{

"type": 1,

"tag": "li",

// children省略了很多属性,表示格式即可

}

],

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值