Vue vs React
相似之处:
- 它们都有使用 Virtual DOM虚拟DOM-CSDN博客;提供了响应式(Reactive)和组件化(Composable)的视图组件。将注意力集中保持在核心库,而将其他功能如路由和全局状态管理交给相关的库。React 比 Vue 有更丰富的生态系统
- 都有支持native的方案,React的RN,vue的Wee下
- 都支持SSR服务端渲染
- 都支持props进行父子组件间的通信
- 性能方面:React 和 Vue 在大部分常见场景下都能提供近似的性能。通常 Vue 会有少量优势,因为 Vue 的 Virtual DOM 实现相对更为轻量一些。
不同之处就是:
- 数据绑定方面,vue实现了数据的双向数据绑定,react数据流动是单向的
- virtual DOM不一样,vue会跟踪每一个组件的依赖关系,不需要重新渲染整个组件树.而对于React而言,每当应用的状态被改变时,全部组件都会重新渲染,所以react中会需要shouldComponentUpdate这个生命周期函数方法来进行控制
- state对象在react应用中不可变的,需要使用setState方法更新状态;在vue中,state对象不是必须的,数据由data属性在vue对象中管理(如果要操作直接this.xxx)
- 组件写法不一样, React推荐的做法是 JSX , 也就是把HTML和CSS全都写进JavaScript了,即'all in js'; Vue推荐的做法是webpack+vue-loader的单文件组件格式,即html,css,js写在同一个文件
vue核心特点
响应的数据绑定
可组合的视图组件
虚拟DOM
运行的js速度是很快的,大量的操作DOM就会很慢,时常在更新数据后会重新渲染页面,这样造成在没有改变数据的地方也重新渲染了DOM节点,这样就造成了很大程度上的资源浪费。
利用在内存中生成与真实DOM与之对应的数据结构,这个在内存中生成的结构称之为虚拟DOM
当数据发生变化时,能够智能地计算出重新渲染组件的最小代价并应用到DOM操作上
MVVM模式(双向数据绑定)
是什么?
- Model层 通过ajax等api完成服务端到客户端model的同步,
- View层 动态视图模板,展示的是VM的数据和状态,不处理状态,做的只是数据绑定的声明、指令的声明、事件绑定的声明
- VM层 把View需要的层数据暴露,对View层的数据绑定声明、指令声明、事件绑定声明负责,处理View层声明的业务逻辑。绑定属性监听,当VM数据变化,V会得到更新;当V中声明了数据的双向绑定,(通常表单元素),框架就会监听V表单值的变化,一旦变化了VM中的数据也会自动更新
实现所需必要操作
- 视图引擎,帮助developer操作DOM
- 数据存储器,通过
Object.defineProperty()
自行封装存取数据的方式。往往封装的是发布 / 订阅模式,来完成数据的监听、数据变更时更新的通知。【数据代理与劫持】- 组件机制,因为有涉及继承、生命周期、组件通信机制,所以MVVM都有提供
Vue的双向绑定原理——数据劫持+(订阅者/发布者)模式_vue订阅者模式原理-CSDN博客
核心Core
响应式
- 数据响应式:数据模型仅仅是普通的 JavaScript 对象,而当我们修改数据时,视图会进行更新,避免了繁琐的 DOM 操作提高开发效率【渲染引擎】
- 双向绑定:数据改变,视图改变;视图改变,数据也随之改变
- 数据驱动:开发过程中仅需要关注数据本身,不需要关心数据是如何渲染到视图
数据代理:通过一个对象代理对另一个对象中属性的操作
//number与age绑定 let number=18; let person={name:'jing',age:'22'} Object.defineProperty(’person‘,’age‘,{value:18,enumable:true,//默认false,遍历时是否参与遍历【枚举】writtable:true ,configurable:true,//控制属性是否可以删除 ,//getterget(){return number;}//setterset(value){number=value; } })
2.x的响应式(Object.defineProperty())
基本原理:通过object.defineProperty()把data对象中所有属性添加到vm上.为每一个添加到vm上的属性,都指定一个getter/setter。在getter/setter内部去操作(读/写))data中对应的属性。
let data={name:'atguigu'} const vm =new Vue({el:"#root",data }) vm.name=vm._data.name=options.data data变了用到data的视图改变
3.x的响应式(proxy)
ES6 之 Proxy 介绍_proxy es6-CSDN博客
Vue3 中的代理原理详解_vue3 代理-CSDN博客
Proxy - JavaScript | MDN
Vue3中Proxy VS Vue2 Object.defineProperty()
- 代理机制可以拦截多种类型的操作,包括属性查找、赋值、枚举、函数调用等,而 Object.defineProperty() 机制只能拦截属性赋值和查找操作。
- 代理机制可以直接监测对象的属性,而 Object.defineProperty() 机制需要遍历对象的所有属性,并为每个属性添加 getter 和 setter,这在对象属性较多时会影响性能。
- 代理机制可以监测到对象新增和删除的属性,而 Object.defineProperty() 机制无法监测到这些操作。
Proxy对象
能够为另一个对象创建代理,该代理可以拦截和重新定义该对象的基本操作,创建一个可以用来代替原始对象的对象,但是它可能会重新定义基本的object操作,如获取、设置和定义属性。代理对象通常用于记录属性访问、验证、格式化或清理输入等等。Proxy还常常和Reflect(方法皆为静态方法)同时使用
var p = new Proxy(target, handler);
Handler操作包括:
- get:拦截对象属性的读取操作。
- set:拦截对象属性的赋值操作。
- deleteProperty:拦截对象属性的删除操作。
- has:拦截 in 操作符的判断操作。
- ownKeys:拦截 Object.keys()、Object.getOwnPropertyNames() 等操作。
- apply:拦截函数的调用操作。
- construct:拦截 new 操作符的调用操作。
基本使用
// 创建一个处理程序对象const handler = {// 拦截目标对象的属性读取操作get(target, prop, receiver) {console.log(`访问了${prop}属性`);// 使用Reflect.get执行目标对象的属性读取操作return Reflect.get(target, prop, receiver);},// 拦截目标对象的属性设置操作set(target, prop, value, receiver) {console.log(`设置了${prop}属性`);// 使用Reflect.set执行目标对象的属性设置操作return Reflect.set(target, prop, value, receiver);},};// 创建一个目标对象const target = {name: "Alice",age: 20,};// 创建一个代理对象const proxy = new Proxy(target, handler);// 使用代理对象执行各种操作console.log(proxy.name); // 访问了name属性,输出Aliceproxy.age = 21; // 设置了age属性console.log(proxy.age); // 访问了age属性,输出21
通过代理对象修改原对象
const target = {}; const p = new Proxy(target, {});p.a = 37; // Operation forwarded to the targetconsole.log(target.a); // 37 (The operation has been properly forwarded!)
访问原对象私有属性
class Secret {#secret;constructor(secret) {this.#secret = secret;}get secret() {return this.#secret.replace(/\d+/, "[REDACTED]");} }const aSecret = new Secret("123456"); console.log(aSecret.secret); // [REDACTED] // Looks like a no-op forwarding... const proxy = new Proxy(aSecret, {}); console.log(proxy.secret); // TypeError: Cannot read private member #secret from an object whose class did not declare it
This is because when the proxy's
get
trap is invoked, thethis
value is theproxy
instead of the originalsecret
, so#secret
is not accessible.const proxy = new Proxy(aSecret, {get(target, prop, receiver) {// By default, it looks like Reflect.get(target, prop, receiver)// which has a different value of `this`return target[prop];}, }); console.log(proxy.secret);
数据劫持
数据劫持是指在访问或修改对象的属性时,对这些操作进行拦截和监视,以便在属性发生变化时能够触发相关的操作。在 Vue 中,数据劫持用于监听数据的变化,以实现双向绑定和响应式更新。
组件渲染时若{{}}、v-bind、v-model等指令绑定数据时,此组件将加入该属性的订阅者(依赖)集合中【getter中实现】,当事件改变数据时将触发【setter】setter中将循环通知订阅者们(组件),并触发组件update()方法更新视图。
https://www.cnblogs.com/ceceliahappycoding/p/10604209.html
发布订阅者模式
观察者模式
设计模式—观察者模式与发布订阅-CSDN博客
Vue响应式原理
声明式渲染
它允许开发者通过简洁的声明来定义用户界面的结构和内容,而不必直接操作DOM。这种方式使得应用的开发更加直观和易于维护。
- 插值:使用双大括号`{{ }}`将数据绑定到模板中,使数据变化能够自动更新到视图。
- v-bind指令:用于动态地绑定元素的属性,使元素的属性值随数据的变化而变化。
- 列表渲染:使用`v-for`指令来声明式地渲染列表,循环遍历数组或对象,并为每个项目渲染相应的元素。
- 条件渲染:使用`v-if`和`v-else`指令根据特定条件来渲染元素,使应用能够根据条件显示或隐藏元素。
- 事件监听:使用`v-on`指令声明式地监听DOM事件,并在事件发生时执行特定的方