当前位置: 首页 > Web前端 > HTML

MVC的分析

时间:2023-03-28 13:29:53 HTML

1、什么是MVC?M是模型,即数据模型,负责与数据相关的工作,包括对数据的增删改查。V是view,也就是视图层,也就是用户可以看到的界面。C为Controller,负责监听用户事件并调用M和V更新数据和视图接下来我们用伪代码分别表示三部分的工作内容1.1Model数据模型//exampleletModel={data:{datasource},create:{adddata},delete:{deletedata},update(data){Object.assign(m.data,data)//用新数据替换旧数据eventBus.trigger('m:update')//eventBus触发'm:update'消息通知View刷新界面},get:{获取数据}}1.2View视图层//例子letView={el:要刷新的元素,html:'refresh页面要显示的内容'init(){v.el:需要初始化刷新元素},render(){刷新页面}}1.3Controllercontroller控制器根据用户的操作调用M和V更新数据和视图通过绑定事件letController={init(){v.init()//初始化Viewv.render()//首先渲染页面c.autoBindEvents()//自动事件绑定eventBus.on('m:update',()=>{v.render()}//当enentsBus触发'm:update'为View刷新},events:{事件被记录并存储在哈希表中},//例如:events:{'click#add1':'add','click#minus1':'minus','click#mul2':'mul','click#divide2':'div',},add(){m.update({n:m.data.n+1})},minus(){m.update({n:m.data.n-1})},mul(){m.update({n:m.data.n*2})},div(){m.update({n:m.data.n/2})},method(){data=newdatam.update(data)//控制器通知模型更新数据},autoBindEvents(){for(letkeyinc.events){//遍历events表,然后自动绑定eventsconstvalue=c[c.events[key]]constspaceIndex=key.indexOf('')constpart1=key.slice(0,spaceIndex)//get'click'constpart2=key.slice(spaceIndex+1)//get'#add1'v.el.on(part1,part2,value)}}1.4MVC实例我们的目标是制作加法、减法、乘法和除法计算器。每次单击加、减、乘、除按钮时,值都会发生变化。基本思路是监听点击事件import'./app1.css'import$from'jquery'consteventBus=$(window)//数据相关mconstm={data:{n:parseInt(localStorage.getItem('n'))},创建(){},删除(){},更新(数据){对象。assign(m.data,data)eventBus.trigger('m:updated')localStorage.setItem('n',m.data.n)},get(){}}//将所有视图相关项放入vconstv={el:空,html:`

{{n}}
+1-1*2÷2
`,init(container){v.el=$(container)},render(n){if(v.el.children.length!==0)v.el.empty()$(v.html.replace('{{n}}',n)).appendTo(v.el)}}//其他都cconstc={init(container){v.init(container)v.render(m.data.n)//view=render(data)c.autoBindEvents()eventBus.on('m:updated',()=>{console.log('here')v.render(m.data.n)})},事件:{'click#add1':'add','click#minus1':'minus','click#mul2':'mul','click#divide2':'div',},添加(){m.update({n:m.data.n+1})},minus(){m.update({n:m.data.n-1})},mul(){m.update({n:m.data.n*2})},div(){m.update({n:m.data.n/2})},autoBindEvents(){for(letkeyinc.events){constvalue=c[c.events[key]]constspaceIndex=key.indexOf('')constpart1=key.slice(0,spaceIndex)constpart2=key.slice(spaceIndex+1)v.el.on(part1,part2,value)}}}exportdefaultc2.EventBus2.1什么是EventBus?EventBus主要用于对象之间的通信。比如上面的例子,Model数据模型和View视图模型并不知道彼此的存在,但是需要进行通信,所以使用了EventBus。总结:使用eventBus可以满足最少的知识原则上m和v不知道对方的底细,但是可以互相调用对方的函数2.2EventBus有哪些API?eventBus提供了on,off,trigger等API,on用于监听事件,trigger用于触发事件如上面在MVC模型中,当M数据模型更新时,triggerconst会触发一个事件m={....update(data){Object.assign(m.data,data)eventBus.trigger('m:updated')//通知视图层我更新了数据,视图应该启动workinglocalStorage.setItem('n',m.data.n)},....}然后在controller中,controller会使用on来监听事件,然后通知viewmodel重新渲染页面constc={init(container){v.init(container)v.render(m.data.n)//view=render(data)c.autoBindEvents()eventBus.on('m:updated',()=>{//控制器将使用on来监听事件,//然后通知视图模型重新渲染页面console.log('here')v.render(m.data.n)})},...}3.表驱动编程当我们需要判断3种以上的情况并做相应的事情时,往往需要写很多Ifelse,这样的代码可读性不是很好。为了增强代码的可读性,我们表驱动编程可以将If条件判断用到的值存储到一个哈希表中,然后从表中获取值实例:在上面的例子中,我需要判断点击的是加减乘除四个按钮中的哪个按钮,然后修改输出的值。按照传统的方式,我们会分别给四个按钮绑定点击事件,然后分别写四个回调函数修改值$button1.on('click',()=>{letn=parseInt($number.text())n+=1localStorage.setItem('n',n)$number.text(n)})$button2.on('click',()=>{让n=parseInt($number.text())n-=1localStorage.setItem('n',n)$number.text(n)})$button3.on('click',()=>{让n=parseInt($number.text())n=n*2localStorage.setItem('n',n)$number.text(n)})$button4.on('click',()=>{让n=parseInt($number.text())n=n/2localStorage.setItem('n',n)$number.text(n)})--------使用事件委托后--------constc={init(container){v.init(容器)v.render(m.data.n)c.BindEvents()}BindEvents(){v.el.on('click','#add1',()=>{m.data.n+=1v.render(m.data.n)})v.el.on('click','#minus1',()=>{m.data.n-=1v.render(m.data.n)})v.el.on('click','#mul2',()=>{m.data.n*=2v.render(m.data.n)})v.el.on('click','#divide2',()=>{m.data.n/=2v.render(m.data.n)})}}但是这样太麻烦了,更新措施:1.绑定加减法为乘除法按钮的父元素,只使用一个事件监听器2.使用哈希表保存按钮和按钮对应的操作constc={events:{'click#add1':'add','click#minus1':'minus','click#mul2':'mul','click#divide2':'div',},add(){m.update({n:m.data.n+1})},minus(){m.update({n:m.data.n-1})},mul(){m.update({n:m.data.n*2})},div(){m.update({n:m.data.n/2})},autoBindEvents(){for(letkeyinc.events){constvalue=c[c.events[key]]constspaceIndex=key.indexOf('')constpart1=key.slice(0,spaceIndex)constpart2=key.slice(spaceIndex+1)v.el.on(part1,part2,value)}}4.模块化模块化就是把一大段代码中相对独立的代码提取成短小精悍的模块。各模块相对独立,便于日后维护和修改。ES6的语法引入了Import和export用于实现模块化。当我们在app1.js中封装controller模型,然后exportcontroller:exportdefaultc//defaultexportexport{c}//另一种导出方式。记得在我们要使用控制器的Main.js中添加花括号:importxfrom'./app1.js'等同于import{defaultasx}from'./app1.js'x.init('#app1')更多关于重命名导出的例子://insidemodule.mjsexport{function1,function2};//insidemain.mjsimport{function1asnewFunctionName,function2asanotherNewFunctionName}from'/modules/module.mjs';

最新推荐
猜你喜欢