码迷,mamicode.com
首页 > Web开发 > 详细

前端MVC

时间:2020-07-20 10:52:45      阅读:76      评论:0      收藏:0      [点我收藏+]

标签:dex   而且   异常   body   sig   control   com   mod   ons   

MVC介绍

MVC的解释千千万,唯一统一的认识就是MCV分别指model、view、controller,至于其它的咱也不知道对错。
MVC是把业务按照M、V、C的功能进行解耦:
Model用来管理业务逻辑相关的数据以及对数据的处理方法
View=render(data)用来展示Model里数据的当下状态,并实时跟随Model更新
Controller负责接受并响应View上用户的交互行为以及对Model内部数据进行操作
刚学编程时,为了完成一个功能,我们想到什么写什么,只要最后能凑出来就成。这种代码常称为“意大利面条”代码,就是一坨*的意思,而且面条之间没有章法可循,你不知道它从哪来,也不知道它到哪去,一旦项目大起来,改代码的工作量比从头写的工作量还大,事情朝着不可控的方向发展了去,改代码的人就很惨。

于是,理清业务逻辑,形成代码规范,方便日后维护,就显得异常重要,so前端开始借鉴后端的架构设计模式,实现了各种MV*框架
(1)第一步

import ‘./app.css‘
import $ from ‘jquery‘

// 数据相关都放到m
const m = {
  data: {
    n: parseInt(localStorage.getItem(‘n‘))
  }
}
// 视图相关都放到v
const v = {
  el: null,
  html: `
  <div id="add">{{n}}</div>
  <button id="btn">+1</button>
  `,
  render(n) {
    $(v.html.replace(‘{{n}}‘, n))
      .appendTo($(‘body>#app‘))
  }
}
// 其他都放c
const c = {
  init() {
    c.ui = {
      $number: $(‘add‘),
        $btn: $(‘btn‘)
    }
    c.bindEvents()
  },
  bindEvents(){
    c.ui.$btn.on(‘click‘, ()=>{
      let n = m.data.n
      n+=1
      localStorage.setItem(‘n‘, n)
      c.ui.$number.text(n)
    })
  }
}

v.render()
c.init()

(2)第二步

import "./app.css"
import $ from "jquery"
import Model from "./base/Model.js"
import View from "./base/View"


const m = new Model({
  data: {
    //初始化数据
    n: parseFloat(localStorage.getItem(‘n‘)) || 100,
  },
  update: function(data){
    Object.assign(m.data, data)
    m.trigger(‘m:updated‘)
    localStorage.setItem(‘n‘, m.data.n.toString())
  }
})

const init = (el)=>{
  new View({
    el: el,
    data: m.data,
    // 初始化html
    html: `
    <div class="output">
      <span id="number">{{n}}</span>
    </div>
    <div class="actions">
      <button id="add">+1</button>
    </div>`,
    render(data){
      if(this.el.children.length !== 0) this.el.empty()
      $(this.html.replace(‘{{n}}‘, data.n)).appendTo(this.el)
    },
    events: {
      ‘click #add‘: ‘add‘,
    },
    add(){
      m.update({n: m.data.n + 1})
    },
  })
}

export default init

表驱动编程

表驱动编程就像封装函数,函数参数(包括)与存在映射关系的对象一一对应,来减少大量重复代码。
再拿上面的例子来说,加上减、乘、除的功能:

events: {
  ‘click #add‘: ‘add‘,
  ‘click #sub‘: ‘sub‘,
  ‘click #mul‘: ‘mul‘,
  ‘click #div‘: ‘div‘,
},
add(){
  m.update({n: m.data.n + 1})
},
sub(){
  m.update({n: m.data.n - 1})
},
mul(){
  m.update({n: m.data.n * 2})
},
div(){
  m.update({n: m.data.n / 2})
}

可以简化成

for(let item in this.events) {
  const operate = this[this.events[item]]
  const spaceIndex = item.indexOf(‘ ‘)
  const eventName = item.slice(0, spaceIndex)
  const element = item.slice(spaceIndex+1)
  this.el.on(eventName, element, operate)
}

EventBus

上面的例子可以看到,View既要从M中取数据,还会根据用户操作来改变M中的数据,这中间少不了两个层之间的交互,以及监听,这就要EventBus来镇场子了。如何监听data的改变的呢?

Model:m.trigger(‘m:updated‘)
View:m.update({n: m.data.n + 1})

当data改变时,会调用m.update()方法,此方法里的m.tigger(‘m:updated‘)会有一个专门的机制来监听它,就是下面的this.on,监听到m:updated就立即从新渲染页面那一块的数据。

this.on(‘m:updated‘, ()=>{
  this.render(this.data)
})

在层层封装之下,底层都离不开EventBus的事件监听,因为数据是活的,会被传递。这里我们可以自己造一个事件,来满足不同条件下的监听需求。然后通过继承,让每个实例都有监听功能。

  • 在jQuery中,有$on,$off,$trigger()来实现监听、解除监听、触发;
  • 在Vue中,则是$on,$off,$emit来实现此功能。

参考链接:https://efe.baidu.com/blog/mvc-deformation/

前端MVC

标签:dex   而且   异常   body   sig   control   com   mod   ons   

原文地址:https://www.cnblogs.com/fourther/p/13343076.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!