react和vue底层原理

对react的理解

react是集于v(视图层)层的一款框架 虚拟dom 和diff算法
react特点
(1)声明式设计
(2)高效 其中高效以现在 虚拟dom 最大限度减少与dom的交互 和diff算法
(3)灵活 体现在可以与已知的框架或库很好的配合
(4)JSX 是js语法的扩展
(5)组件化 构建组件,是代码的更容易得到复用 , 比较建议在大型项目的开发
(6)单项数据 : 实现单项数流 从而减少代码复用

比虚拟dom的比较, 使用diff算法
同级比较 加key
setstate是个异步,  多次合并区别,执行一次渲染

react的diff算法?

1.把树形结构按照层级分解,只比较同级元素。时间复杂度为n
2.给列表结构的每个单元添加唯一的 key 属性,方便比较。
3.React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
4.合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, 
React 检查所有标记 dirty 的 component 重新绘制.
5.选择性子树渲染。开发人员可以重写 shouldComponentUpdate 提高 diff 的性能。
 

虚拟dom是什么,为什么虚拟dom会提升代码性能?

	虚拟 dom 相当于在 js 和真实 dom 中间加了一个缓存,
	利用 dom diff 算法避免了没有必要的 dom 操作,从而提高性能。
	用 JavaScript 对象结构表示 DOM 树的结构;然后用这个树构建一个真正的 DOM 树,
	插到文档当中当状态变更的时候,重新构造一棵新的对象树。然后用新的树和旧的树进行比较,
	记录两棵树差异把 2 所记录的差异应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了

Virual DOM是用JS对象记录一个dom节点的副本,当dom发生更改时候,先用
虚拟dom进行diff,算出最小差异,然后再修改真实dom。

当用传统的方式操作DOM的时候,浏览器会从构建DOM树开始从头到尾执行一遍流程,效率很低。
而虚拟DOM是用javascript对象表示的,而操作javascript是很简便高效的。
虚拟DOM和真正的DOM有一层映射关系,很多需要操作DOM的地方都会去操作虚拟DOM,
最后统一一次更新DOM。因而可以提高性能

虚拟DOM其实就是真实的js对象虚拟DOM提高了react的性能,每次数据更新后都会重新计算上虚拟DOM,并和上一次的虚拟DOM进行对比,对方法变化的部分进行批量更新。react中也提供了shouldComponentUpdate生命周期的回调,来减少数据变化后不必要的虚拟DOM对比过程。保证性能

虚拟DOM的缺点:
1. 代码更多,体积更大
2. 内存占用增大
3. 小量的单一的dom修改使用虚拟dom成本反而更高,不如直接修改真实dom快

React 中 keys 的作用是什么?

render () {
  return (
    <ul>
      {this.state.todoItems.map(({item, key}) => {
        return <li key={key}>{item}</li>
      })}
    </ul>
  )
}

Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。
此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。

避免出错
例如  数组循环出来三项,每一项前面有一个多选框,假设第一个多选框勾选了,然后我再动态添加新的元素,会
发现新添加的元素就会被勾选了,这就是个问题!key值,这样的话就可以解决了。

Vue、React中循环遍历为什么必须有key

  • vue和react都是在操作虚拟dom,并且根据diff算法进行新旧dom对比,从而更新dom
  • key` 的特殊属性主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes。如果不使用 key,Vue 会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用 key,它会基于 key 的变化重新排列元素顺序,并且会移除 key 不存在的元素。
  • key值的存在保证了唯一性,可以用于dom的重新渲染或是就地复用
  • 更精准–>在虚拟dom节点中赋予key值,会更加快速的拿到需要的目标节点,不会造成就地复用的情况,对于节点的把控更加精准。

MVC、MVP、MVVM

> MVVM 模式,顾名思义即 Model-View-ViewModel 模式。
> 它萌芽于2005年微软推出的基于 Windows 的用户界面框架 WPF ,
> 前端最早的 MVVM 框架 knockout 在2010年发布。
>
> Model 层: 对应数据层的域模型,它主要做域模型的同步。
> 通过 Ajax/fetch 等 API 完成客户端和服务端业务 Model 的同步。
> 在层间关系里,它主要用于抽象出 ViewModel 中视图的 Model。
>
> View 层:作为视图模板存在,在 MVVM 里,整个 View 是一个动态模板。
> 除了定义结构、布局外,它展示的是 ViewModel 层的数据和状态。
> View 层不负责处理状态,View 层做的是 数据绑定的声明、 指令的声明、 事件绑定的声明。
>
> ViewModel 层:把 View 需要的层数据暴露,并对 View 层的 数据绑定声明、 指令声明、 
> 事件绑定声明 负责,也就是处理 View 层的具体业务逻辑。ViewModel 底层会做好绑定属性的监听。
> 当 ViewModel 中数据变化,View 层会得到更新;而当 View 中声明了数据的双向绑定(通常是表单元素),
> 框架也会监听 View 层(表单)值的变化。一旦值变化,
> View 层绑定的 ViewModel 中的数据也会得到自动更新。
>
> **MVVM的优缺点**
>
> 优点:
>
> 1. 分离视图(View)和模型(Model),降低代码耦合,提高视图或者逻辑的重用性: 
> 比如视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定不同的"View"上,
> 当View变化的时候Model不可以不变,当Model变化的时候View也可以不变。
> 你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
> 2. 提高可测试性: ViewModel的存在可以帮助开发者更好地编写测试代码
> 3. 自动更新dom: 利用双向绑定,数据更新后视图自动更新,让开发者从繁琐的手动dom中解放
>
> 缺点:
>
> 1. Bug很难被调试: 因为使用双向绑定的模式,当你看到界面异常了,有可能是你View的代码有Bug,
> 也可能是Model的代码有问题。数据绑定使得一个位置的Bug被快速传递到别的位置,
> 要定位原始出问题的地方就变得不那么容易了。另外,数据绑定的声明是指令式地写在View的模版当中的,
> 这些内容是没办法去打断点debug的
> 2. 一个大的模块中model也会很大,虽然使用方便了也很容易保证了数据的一致性,当时长期持有,
> 不释放内存就造成了花费更多的内存
> 3. 对于大型的图形应用程序,视图状态较多,ViewModel的构建和维护的成本都会比较高


mvc三层是可以互相的调用,流程上没有过多的限制
	m:model 数据模型层  (数据与数据库的操作的一部分逻辑  增删查改操作  java/dao层)
	v:view  视图层
	c:controller 控制器
	c的作用是将m层的数据在v层上进行显示。


mvp是mvc的升级,m不能调用p层,v也不能去调用p层,只有p层可以调用mv.最终暴露用户的是p这一层

mvvm 
	m:model 
	v:view  
	vm:viewmodel  
vm层可以感知数据的变化,然后实时的渲染最新的视图,并且这个是自动的操作。(Object.defineProperty)



react只是mvc里面的v层。因为当数据发生变化了,视图是不会渲染最新视图,必须内部调用setState进行更新,
然后视图才可以变成最新的视图。 这个操作是我们手动实现的。

vue

Vue采用的就是MVVM模式,这是从MVC衍生出来的
	区别:视图与ViewModle直接的关系特别的紧密
	v-model就是vue提供的指令   操作dom

mvvm就是为了解决mvc反馈不及时的问题
​    MVVM与MVC最大的区别就是:
​    它实现了View和Model的自动同步,也就是当Model属性改变时,
​    我们不用再自己手动操作Dom元素,来改变View的显示,
​    而是改变属性后该属性对应View层显示会自动改变
view <==> viewModel <==> model

Vue实现数据双向绑定的原理:Object.defineProperty

  • vue实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应监听回调。当把一个普通 Javascript 对象传给 Vue 实例来作为它的 data 选项时,Vue 将遍历它的属性,用 Object.defineProperty() 将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。
  • vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer,Compile和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —›视图更新;视图交互变化(input)—›数据model变更双向绑定效果
VUE的数据绑定    ,通俗说:数据变,页面变     
vue中 data中的数据都会经过Object.defineProperty进行处理,有了getter和setter
VUE 2.X 版本响应式原理的根本 Object.defineProperty
VUE 3.0 响应式原理是通过proxy原理,为什么要变革?
因为 Object.defineProperty监听不到对象属性的增删、数组元素和长度的变化

v-model的原理

  • 用于表单的据双向绑定的指令**
    做了两个操作:
    • v-bind 绑定了一个value的属性
    • v-on 把当前元素绑定到了一个事件上**
    • Vue 的依赖追踪是【原理上不支持双向绑定,v-model 只是通过监听 DOM 事件实现的语法糖】
Vue的双向数据绑定是由数据劫持结合发布者订阅者实现的。
数据劫持是通过Object.defineProperty()来劫持对象数据的setter和getter操作。
在数据变动时做你想做的事

原理 : 通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,
最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 => 视图更新 
在初始化vue实例时,遍历data这个对象,给每一个键值对利用Object.definedProperty对data的键值对
新增get和set方法,利用了事件监听DOM的机制,让视图去改变数据

在Vue中,对单向数据流与数据双向绑定的理解

  • 单向数据流:父组件中的数据通过props流动到子组件中,并且父组件中的数据发生改变时,子组件会自动接收到这个修改后的数据,并且更新内容,子组件不能修改由父组件传递过来的数据,好处就是:数据的流动方向可以跟踪,流动单一,追查问题的时候可以方便快捷。

  • 数据双向绑定:v-model是一个语法糖,当绑定在input中时,输入框的内容发生变化时,data中的数据同步变化,即:view => model 的变化,data中的数据发生变化时,文本节点的内容同步变化,即:model => view的变化Vue内部通过Object.defineProperty方法属性拦截的方式,把data对象里每个数据的读写转化成getter/setter,当数据变化时通知视图更新

# Proxy 和Defineproperty的区别

> Proxy的优势如下:
>
> - Proxy可以直接监听对象而非属性
> - Proxy可以直接监听数组的变化
> - Proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等Object.defineProperty不具备的
> - Proxy返回的是一个新对象,我们可以只操作新的对象达到目的,而Object.defineProperty只能遍历对象属性直接修改
> - Proxy作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利


你可能感兴趣的:(react,react)