「每日一题」MVC 是什么?(续1)

上期讲了「后端 MVC」,本期讲「前端 MVC」。

前后端分离

前端 MVC 就要从前后端分离讲起了。

前后端分离是指

一个页面分为两部分,浏览器上面的工作交给前端做,服务器上面的工作交给后端做(人员分离)

页面开发流程是这样的

1. 浏览器第一次加载的页面只是一个占位符,比如这样

<body>
  <div id=app></div>
</body>

2. 前端将其他 HTML 和从服务器获取的数据填到占位符里

伪代码:

$.get('/user/1').then(function(user){

  template = (
    <h1>{{ name }}</h1>
  )

  content = template.replace('{{ title }}', user.name)

  $app.html(content)

})

3. 用户提交数据时,前端用 AJAX 提交异步请求

$form.on('submit', function(){
  $.post('/user/1', $form.serialize()).then(function(){
    alert('提交成功')
  })
})

老司机的总结


前端老司机发现自己每个项目都要重复上面的流程,于是也想总结一下,归纳一下,抽象一下。

假设我们要做一个用户中心页面。

Model - 封装数据操作

对用户的增删改成其实都是异步请求,我能不能封装到一起呢?

var userModel = {
  find: function(id){
    return $.get('/user/'+id).then(function(user){
      $.extend(userModel, user)
    })
  },
  save: function(id, data){
    return $.post('/user/'+id, data)
  }
}

出了这些,还有用户数据的校验

userModel.validate = function(){
  if(this.name === '') return false
  if(this.password === '') return false
  return true
}

这样一来,数据相关的操作就都放到这个 model 上了。

View - 视图渲染

前端的视图也是 HTML,由于 HTML 里面没有数据,所以我们一般都要将数据与 HTML 混合起来

上面代码是这样做混合的:

content = template.replace('{{ title }}', user.name)

显然这样的方案功能不够强大,于是前端们用正则写出很多强大的模板引擎,如 Handlebars.jsReact,最终实现的效果大致是:

content = templateEngine( template, user )

content 就是带有数据的 HTML 了。

Controller - 控制器主要是打杂的

还有哪些事情没做,都交给 Controller 吧:

  1. 将 content 塞到页面里
  2. 浏览器事件监听 - 用户点击视图后去更新数据(如 user)
  3. 数据事件监听 - user 数据更新后去更新视图

对应的代码:

controller = {
  model: userModel,
  element: $app,
  template: '<h1>{{ name }} </h1>........',
  events: {
    'click button': 'onButtonClick',
    'submit form' : 'onSubmitForm'
  },
  modelEvents: {
    'update': 'onModelUpdate',
    'remove': 'onModelRemove'
  },
  init: function(){
    var content = templateEngine(this.template, userModel)
    this.element.append($app)
    
    // 遍历 events 并绑定对应的方法
    // 遍历 modelEvents 并绑定对应的方法
  },
  onButtonClick: function(){...},
  onSubmitForm: function(){...},
  onModelUpdate: function(){...},
  onModelRemove: function(){...}
}

总结一下:

  1. Controller 监听 Model 变化,Model 一变,Controller 就会去更新 View。
  2. Controller 监听用户交互,用户点了提交或修改按钮,Controller 就要去更新 Model。


注意,一个页面可以有多个 Controller,每个 Controller 负责一个大 div 即可。

Router - 路由

前端 MVC 有路由吗?可以有,也可以没有。

如果只是在每个页面局部使用 MVC,那么就不需要路由。

如果整站是一个单页面,那么就要处理 URL 的变化了(用 PushState API 或者 URL Hash)。


MVC 里面最复杂的部分是 Controller,它做了太多机械的、繁琐的事情,比如绑定事件、更新 DOM、更新数据,这也为前端 MVC 没落留下了隐患,后面的 MVP、MVVM、FLUX 很好地解决这一问题(同时引入了其他问题)。不过 MVC 的概念,我们还是有必要了解的。


更多前端交流,尽在前端交流5群:152052597

编辑于 2016-10-20

文章被以下专栏收录