问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

利用Object.defineProperty简单实现MVVM的订阅与数据劫持

发布网友 发布时间:2024-10-05 15:57

我来回答

1个回答

热心网友 时间:2024-10-23 17:50

MVVM简介

MVVM是一种设计模式,或者也可以称为一种架构模式。它的全拼是Model-View-ViewModel。

Model代表模型

View代表视图

ViewModel代表了一个控制器

这其中,我们可以将model看作是后端接口返回的数据

{name:'晴天',age:'18',mark:'always18'}

而view就是前端显示在浏览器中让用户看到的页面

那一段json数据是如何显示到页面里的呢?这就是ViewModel负责的事情。

所以,它们之间的关系可以用一个图来表示

前端最常见的MVVM的框架,应该就是

AngularJs,不过这个框架,国内用的貌似比较少

尤大大的vue,我们经常在vue的demo中看到varvm=newVue(...),这个vm就是viewmodel的简写。

响应式原理

MVVM的初衷是想利用数据绑定函数,从视图层面删除所有和界面数据渲染逻辑相关的代码。

那么,应该如何使用或者如何编写数据绑定函数,才能达到这样的效果呢?

我们看vue的表现:

<divid="counter">Counter:{{counter}}</div>constCounter={data(){return{counter:0}}}Vue.createApp(Counter).mount('#counter')

当然这个例子和Object.defineProperty没有关系,我只是在这里体现“数据绑定后从视图层面删除了和界面数据渲染逻辑相关的代码”这句话

很明显,我们没有自己编写

document.getElementById(counter).innerText=counter

或者

$('#counter).text(counter)

类似这种的渲染代码。

你可能觉得这只是一行代码啊,这么简单。

其实不然,假如我们需要counter做递增

mounted(){setInterval(()=>{this.counter++},1000)}

你就知道MVVM到底帮我们省了多大的力气。

好了,到这里已经展示了MVVM的表现,那么回到正题,如何利用Object.defineProperty简单实现MVVM呢?

其实vue2的响应式原理,是数据劫持,即数据变化的时候,自动重新渲染相关页面。

其实这个需求是非常容易的,但是首先要理解一个方法,叫做Object.defineProperty,理解之后大部分人都可以模拟一个简单的实现。

虽然跟vue差很多,但是面试考察的也不是让你去写个vue。

defineProperty数据劫持

Object.defineProperty方法会在一个对象上添加一个新的属性,或者修改一个对象的已有属性,最后返回此对象.

Object.defineProperty方法可以接收三个参数

object(required,要定义属性的对象)

propertyname(required,要定义或修改的属性的名称)

descriptor(required,要定义或修改的属性描述符)

Object.defineProperty(object,propertyname,descriptor)

针对descriptor,它是一个对象类型,用于配置propertyname的属性描述符,因此descriptor的属性可以选择如下两种中的一种:

数据描述符

key值类型描述默认值valueanyobject.propertyname的值undefinedwritablebooleanobject.propertyname是否可以被赋值运算符修改falseconfigurablebooleanobject.propertyname是否可以被修改和删除falseenumerablebooleanobject.propertyname是否可以被枚举false

存取描述符

key值类型描述默认值getfunction读取object.propertyname时调用的函数undefinedsetfunction设置object.propertyname时调用的函数undefinedconfigurablebooleanobject.propertyname是否可以被修改和删除falseenumerablebooleanobject.propertyname是否可以被枚举false

小伙伴可能看出来了,数据描述符和存取描述符具有共同的key,也有不同的key,那么当一个描述符内部没有value、writable、get和set时,它默认是一个数据描述符。

下面的例子展示了存取描述符的作用:

letdata={},temp='aa'Object.defineProperty(data,'key1',{set(value){console.log('thisisanewvalue:'+value)temp=value//somecodelike$('div').html(value)willautomaticexecutewhenkey1changed},get(){returntemp}})data.key1='Jack'

当我们在浏览器运行上面这段代码,控制台会输出:

thisisanewvalue:Jack

这就是存取描述符的作用,他可以用来做数据劫持。

订阅模式

我们题目要实现的订阅与数据劫持,就是要通过Object.defineProperty的存取描述符来实现。

订阅器,我们可以简单的将其理解为一个队列,队列内都是即将在某个时刻执行的函数。

当然,为了方便查找,我们可以将其定义为一个对象类型,其中的每个属性,都是数组类型。

vara={a:[],b:[],c:[]}

下面我们来实现一个订阅器:

letDeep={deepList:{},listen(key,fn){if(!this.deepList[key])this.deepList[key]=[]this.deepList[key].push(fn)},trigger(){letkey=Array.prototype.shift.call(arguments)letfnList=this.deepList[key]if(!key||!fnList||!fnList.length)returnfalsefor(leti=0,fn;fn=fnList[i++];){fn.apply(this.arguments)}}}将订阅器与数据劫持绑定到一起

这里就是要实现,数据劫持发生后,去执行订阅器内相应的代码。

这样,就可以实现类似vue的,改变了某个message,页面能同步渲染最新的结果。

这部分代码的逻辑十分简单:

首先,我们通过Deep.listen将页面标签与内容绑定到一起并放入到订阅器中

然后,我们在数据劫持中调用订阅器的trigger方法,更新数据的同时同步更新html

letdataHijack=({data,tag,datakey,selector})=>{letvalue='',el=document.querySelector(selector);Object.defineProperty(data,datakey,{get(){returnvalue},set(newVlaue){value=newVlaueDeep.trigger(tag,newVlaue)}})Deep.listen(tag,content=>{el.innerHTML=content})}

作者:晴天同学

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
轻度慢性萎缩性胃炎 活动期,伴轻度肠 化 胃角多发糜烂。医生说了我... 胃窦粘膜慢性轻度萎缩性炎伴轻度肠化胃窦粘膜慢性轻度萎缩性炎? 芬兰留学读研费用是多少 芬兰留学读研时间 去芬兰留学学费生活费一年要多少 芬兰留学读研费用是多少? 芬兰留学读研学费多少? 感冒好多天了,可不可以打蓝球或者其它运动出出汗啊? 感冒打喷嚏,鼻塞然后可以让自己多出出汗吗 宝宝感冒了能去游泳吗 在word文档中如何打竖着的破折号在word文档中如何打竖着的破折号的符号... 如何在word2010文档中输入破折号? miwifi是什么路由器 美的空调显示eh03是什么故障代码? 美的空调03eh是什么问题? 美的空调03eh是什么故障? 淘宝新品打标有什么用? 如何打出长破折号? 大家说说高考资源网好不好啊。知道的介绍下。ks5u的那个。 高考资源网在线充值怎样啊,点数能及时加上吗,我还急着下载试题呢? 在高考资源网选择个人用户充值,是不是在什么地方都可以随时下载资料呀... 怎么下载高考资源网啊 Liquor Whisper的歌词是什么? 1991年我国作为主权国家,加入了“APEC”,它是下列哪一国际组织... APEC卡的实施情况 美博空调故障显示屏不显示怎么办 如何分辨欧泊 ZHX欧泊分享第一弹——欧泊的品类产地及简史 入坑欧泊前应该了解哪些知识? 欧泊原石鉴定方法 中介找中介帮买房“吃差价”,这种行为是否违法? 麝香为什么会导致不孕 香水里面的麝香会导致不孕吗 请问;老公用含有麝香成份的香水对要怀孕的有影响吗? 麝香是如何形成的 我有野生麝香一枚,收藏30余年,哪位好心人知道当前收购价格,请告知... 二手车如何检查气囊在不在 vue-cli是什么 怎样查看电脑的内存颗粒? 朝鲜为什么不参加apec会议 求这张贝阿朵莉切高清无水印原图! 求T.O.P这四张无水印原图 谢谢 求原图,无水印的,谢谢 档案丢失了补办会影响科股级任免么 三星a7一直卡在开机页面并不能重启如何解决? 什么抢单软件好用? 一海豚在水池中自由游弋,水池为长40m、宽30m的长方形,则此海豚嘴尖离岸... 桐庐孝顺金是什么意思? 微保上孝亲保孝顺金怎么样?孝亲保孝顺金保障有哪些? 吃什么水果补精养肾啊?求解