概述
MVC 是一种思想,它会让我们写代码时更加简洁、高效、模块化,了解这种方法对于前端程序员来说是很有必要的。首先说明下 MVC 代表的含义:
- M ==> Model ==> 模型
- V ==> View ==> 视图
- C ==> Controller ==> 控制器
MVC 各自作用
MVC 主要是按功能划分模块
- view:js 代码所操纵的视图(HTML),负责显示给用户和通知 controller(控制器)
-
Model:view(视图)所需要的所有的数据操作,包括:
- 初始化数据
- 读取数据
-
存入数据
负责和向 server(服务器)请求数据和响应 server(服务器)
-
controller:所有的逻辑操作,负责监控和更新 view(视图) + 调用和接收 model(数据)
MVC 使用技术点
-
立即执行函数,这里有所有的立即执行函数的写法,但是这里推荐大家使用
1
!function(){}.call()
立即执行函数避免了我们是用全局变量,隔离作用域,从而达到了使用局部变量的目的
-
闭包
闭包就是如果一个函数使用了它范围外的值,那么这个函数 + 这个变量就叫做闭包
闭包使得模块之间可以进行相互访问。具体实现:
- 函数 fn 中局部变量 obj 和 return 的函数构成了闭包
- return 的函数便是接口,可以供外部调用,从而来操纵局部变量 obj
- 外部除了使用函数 fn 的接口,没有任何其他方法可以访问到局部变量 obj
-
全局变量
模块与模块之间是在不同的 js 文件中,例如模块2想去操纵模块1的数据,通过上述方式显然是不够的,那么只能退而求其次,使用全局变量。具体实现:
通过使用全局变量保存了匿名函数的地址,从而全局都可以使用这个全局属性
总结
以上3种技术点的结合 ==> 立即执行函数 + 闭包 + 全局变量 实现了 MVC 中 Controller(控制器) 的相应需求,从而让前端更好的使用 MVC 思想
细节问题
- this 的使用,在 MVC 中要着重使用 this
- 箭头函数,其实在 MVC 中使用箭头函数,主要就是为了 this ,原因在于箭头函数内外 this 不变
- HTML 中每一块都是一个 view ,当我们为 HTML 分块的时候,是可以嵌套的,所以我们的 view 也是可以嵌套的
使用模板
1 | !function(){ |
实际应用
// 这是第一次写的,放弃 | |
!function () { | |
let view = View('section.leaveMessage') | |
let model = Model({date:'Message'}) | |
let controller = { | |
view: null, | |
model: null, | |
ol: null, | |
form: null, | |
countMessage: null, | |
content: null, | |
submit: null, | |
username: null, | |
init:function () { | |
this.view= view | |
this.model= model | |
this.ol= view.querySelector('#messageList') | |
this.form= view.querySelector('section.leaveMessage form') | |
this.countMessage= view.querySelector('#countMessage') | |
this.submit= view.querySelector('#leaveMessageSubmit') | |
this.content= view.querySelector('#leaveMessageContent') | |
this.username= view.querySelector('#leaveMessageUsername') | |
this.model.initAV() | |
this.readingDate()// this.readingDate.call(this) | |
this.bindEvents()//this.bindEvents.call(this) | |
}, | |
readingDate:function () { | |
this.model.fetch().then((messages)=> { | |
this.countMessage.textContent= messages.length | |
messages.forEach((message)=> { | |
// let data = message.set('status', 1) | |
this.createLi(message) | |
}) | |
}) | |
}, | |
bindEvents:function () { | |
this.form.addEventListener('submit', (event) => { | |
event.preventDefault() | |
this.submit.classList.remove('active') | |
let username = view.querySelector('form input[name=username]').value | |
let content = view.querySelector('form input[name=content]').value | |
this.model.save({ | |
'username': username, | |
'content': content | |
}).then((object)=> { | |
let date = object.set('status',1) | |
this.countMessage.textContent= parseInt(countMessage.textContent,10) + 1 | |
this.createLi(date) | |
document.querySelector('#leaveMessageUsername').value= '' | |
document.querySelector('#leaveMessageContent').value= '' | |
}) | |
}) | |
this.content.addEventListener('input', () => { | |
this.submitVerification() | |
}) | |
this.username.addEventListener('input', () => { | |
this.submitVerification() | |
}) | |
}, | |
submitVerification:function(){ | |
if (this.content.value!== '' && this.username.value!== '') { | |
this.submit['disabled']= false | |
this.submit.classList.add('active') | |
} else { | |
this.submit['disabled']= true | |
this.submit.classList.remove('active') | |
} | |
}, | |
createLi:function (object) { | |
let li = this.createEle('li',this.ol,'') | |
let svg = this.createEle('svg', li,'icon') | |
let use = this.createEle('use', svg,'') | |
use.setAttribute('xlink:href',"#icon-username") | |
let a = this.createEle('a', li,'username') | |
a.textContent = object.attributes.username | |
let p = this.createEle('p', li,'leaveMessageContent') | |
p.textContent = object.attributes.content | |
let span = this.createEle('span', li,'time') | |
this.writeTime(object, span) | |
}, | |
createEle:function (ele,parent, klassName) { | |
let element = document.createElement(ele) | |
element.className= klassName | |
parent.appendChild(element) | |
return element | |
}, | |
writeTime:function writeTime(object, span) { | |
let year = object.updatedAt.getFullYear() | |
let month = object.updatedAt.getMonth()+ 1 | |
let date = object.updatedAt.getDate() | |
let hourse = object.updatedAt.getHours() | |
let minutes = object.updatedAt.getMinutes() | |
let seconds = object.updatedAt.getSeconds() | |
span.textContent = year + '年' + month + '月' + date + '日 ' + hourse + ':' + minutes + ':' + seconds | |
}, | |
} | |
controller.init(view,model) | |
}.call() |