概述

MVC 是一种思想,它会让我们写代码时更加简洁、高效、模块化,了解这种方法对于前端程序员来说是很有必要的。首先说明下 MVC 代表的含义:

  • M ==> Model ==> 模型
  • V ==> View ==> 视图
  • C ==> Controller ==> 控制器

MVC 各自作用

MVC 主要是按功能划分模块

  1. view:js 代码所操纵的视图(HTML),负责显示给用户和通知 controller(控制器)
  2. Model:view(视图)所需要的所有的数据操作,包括:

    • 初始化数据
    • 读取数据
    • 存入数据

      负责和向 server(服务器)请求数据和响应 server(服务器)

  3. controller:所有的逻辑操作,负责监控和更新 view(视图) + 调用和接收 model(数据)

MVC 使用技术点

  1. 立即执行函数,这里有所有的立即执行函数的写法,但是这里推荐大家使用

    1
    !function(){}.call()

    立即执行函数避免了我们是用全局变量,隔离作用域,从而达到了使用局部变量的目的

  2. 闭包
    闭包就是如果一个函数使用了它范围外的值,那么这个函数 + 这个变量就叫做闭包
    闭包使得模块之间可以进行相互访问。具体实现:
    闭包 + 操作局部变量

    • 函数 fn 中局部变量 obj 和 return 的函数构成了闭包
    • return 的函数便是接口,可以供外部调用,从而来操纵局部变量 obj
    • 外部除了使用函数 fn 的接口,没有任何其他方法可以访问到局部变量 obj
  3. 全局变量
    模块与模块之间是在不同的 js 文件中,例如模块2想去操纵模块1的数据,通过上述方式显然是不够的,那么只能退而求其次,使用全局变量。具体实现:
    全局变量
    通过使用全局变量保存了匿名函数的地址,从而全局都可以使用这个全局属性

总结

以上3种技术点的结合 ==> 立即执行函数 + 闭包 + 全局变量 实现了 MVC 中 Controller(控制器) 的相应需求,从而让前端更好的使用 MVC 思想

细节问题
  1. this 的使用,在 MVC 中要着重使用 this
  2. 箭头函数,其实在 MVC 中使用箭头函数,主要就是为了 this ,原因在于箭头函数内外 this 不变
  3. HTML 中每一块都是一个 view ,当我们为 HTML 分块的时候,是可以嵌套的,所以我们的 view 也是可以嵌套的

使用模板

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
!function(){
let view = 操纵的 HTML 模块
let model = {
init: function(){},
fetch: function(){} // 注意此处最好返回 Promise 对象
save: function(){} // 注意此处最好返回 Promise 对象
}
let controller = {
view = null,
model = null,
...... = null,
init: function(){
this.view = view
this.model = model
......
this.bindEvents()
},
bindEvents: function(){
// 绑定事件,与绑定事件无关的放在 controller 属性上
},
......
}
controller.init( controller,model )
//controller.init.call( controller,view, model )
}.call()

实际应用

// 这是第一次写的,放弃
   
  !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()