作者:蚁走天涯路 | 来源:互联网 | 2023-09-10 16:05
MV*模式MVCMVPMVVM1MVC一个利用分为三局部模型(Model):数据保留应用程序的数据、管制与批改这些数据的业务规定Model扭转时:告诉View,为View提供查问Model相干状态的能力,为Controller提供拜访封装在Model外部的应用程序性能的能力。视图(View):用户界面组织Model的内容Model扭转时:View负责保护数据体现的统一
MV*模式
- MVC
- MVP
- MVVM
1 MVC
一个利用分为三局部
-
模型 (Model):数据保留
应用程序的数据
、管制与批改这些数据的业务规定
Model扭转时
:告诉View,为View提供查问Model相干状态的能力,为Controller提供拜访封装在Model外部的应用程序性能的能力。
-
视图 (View):用户界面
组织Model的内容
Model扭转时
:View负责保护数据体现的一致性,同时View将用户的申请告诉Controller
-
控制器 (Controller):业务逻辑
应用程序的行为
解释来自View的用户申请,把申请映射为行为,再由Model实现这些行为。
结构图:
- View传送指令到Controller
- Controller实现业务逻辑后,要求Model扭转状态
-
Model将新的数据发送到View,用户失去反馈
承受指令的形式
由View承受指令,传递给Controller
Controller间接承受指令
2 MVP
- 模型(Model):提供数据
- 视图(View):用户界面
- 示意器(Presenter):逻辑的解决
结构图
- View与Model无分割,都通过Presenter传递
- View中不部署任何业务逻辑 – 被动视图
- 所有逻辑都部署在Presenter
与MVC的区别
View不能间接从Model中读取数据
3 MVVM
基本上与MVP模式统一
- 模型(Model):保留数据
- 视图(View):用户界面
-
数据驱动(View-Model):业务逻辑
VM负责转换Model中的数据对象
结构图
- 操作View时,ViewModel感知变动,告诉Model产生相应的变动,若Model扭转时,ViewModel感知变动,告诉View进行更新
- ViewModel与View双向数据绑定,Model通过接口申请数据交互,承前启后。
双向数据绑定
- Vue2:Object.defineProperty()
- Vue3:Proxy代理
1 Vue2双向绑定实现
Object.defineProperty(obj,prop,description)
原理简析,不做依赖收集
/**
* 对Object.defineProperty()进行封装
*/
function defineReactive(obj, key, value) {
//递归 - 对象的属性仍是对象
observe(value);
//变动侦测
Object.defineProperty(obj, key, {
get() {
return value;
},
set(newVal) {
if (newVal !== value) {
updateView();
value = newVal;
observe(newVal)
}
}
})
}
/**
* 对一个对象所有属性的变动侦测
*/
function observe(target) {
//非对象,间接返回
if (typeof target !== 'object') {
return target;
}
//将每个属性转换为getter和setter模式
for (let key in target) {
defineReactive(target, key, target[key])
}
}
//模仿更新视图的办法
function updateView() {
console.log("更新视图");
}
通过间接调用observe侦测对象属性的变动
存在的问题
- 性能较差
- 对象上新增属性无奈侦测
- 扭转数组的length属性无奈被侦测
2 Vue3双向绑定实现
Proxy是一种能够拦挡并扭转底层Javascript引擎操作的包装器,性能更优异
数组能够像对象一样触发get与set
【js】代理与反射(Proxy/Reflect)
【阮一峰】ES6规范-Proxy
原理简析,不做依赖收集
根本流程
cosnt o = {name:"张三"}
const proxy = new Proxy(o,{
get(target,key,receiver){
console.log("读取属性值")
},
set(target,key,value,receiver){
console.log("设置属性值")
},
deleteProperty(target,key){
console.log("删除属性")
}
})
proxy.name; //读取属性值
proxy.name = "李四";//设置属性值
delete proxy[name] ;//删除属性
自定义的业务逻辑
//判断是否是对象
function isObj(val) {
return val !== null && typeof val === "object"
}
//判断以后对象是否有指定属性
function hasOwn(target, key) {
return target.hasOwnProperty(key)
}
//存储代理信息
const toProxy = new WeakMap()
const toRaw = new WeakMap()
/**
*创立响应式对象
*/
function createReactiveObj(target) {
//指标不是对象,间接返回target
if (!isObj(target)) {
return target
}
const proxy = toProxy.get(target)
//如果指标对象已被代理,间接返回代理对象
if (proxy) {
return proxy
}
//如果指标对象是代理对象,并有对应的真的对象,间接返回
if (toRaw.has(target)) {
return target
}
//生成代理对象
const observed = new Proxy(target, {
get(target, key, receiver) {
console.log("读取值");
const result = Reflect.get(target, key, receiver)
//为返回值增加代理
return isObj(result) ? reactive(result) : result
},
set(target, key, value, receiver) {
//判断指标对象是否曾经存在该属性
const hasProperty = hasOwn(target, key)
const oldVal = Reflect.get(target, key)
if (!hasProperty) {
console.log("新增属性");
} else if (oldVal !== value) {
console.log("批改属性");
}
return Reflect.set(target, key, value, receiver)
},
deleteProperty(target, key) {
console.log("删除值");
return Reflect.deleteProperty(target, key)
}
})
//增加指标对象与代理对象到Map
toProxy.set(target, observed)
toRaw.set(observed, target)
return observed
}
//响应式入口
function reactive(target) {
return createReactiveObj(target)
}
与根本流程相比,自定义实现的性能
Proxy的handler中还能够写很多办法,以满足简单的业务