对MVC的理解

一、MVC 是什么?

M : model,即数据模型,负责数据相关的任务,包括对数据的增删改查。
V : view,即视图层,即用户能看得到的界面。
C : Controller,即控制器,负责监听用户事件,然后调用 M 和 V 更新数据和视图。

MVC 并没有一个比较明确的做法,MVC 其实就是将代码变的结构化的一种抽象概念。

1.1 Model 数据模型
//示例
let Model = {
  data: { 数据源 },
  create: { 增加数据 },
  delete: { 删除数据 },
  update(data) {
    Object.assign(m.data, data); //用新数据替换旧数据
    eventBus.trigger("m:update"); //eventBus触发'm:update'信息,通知View刷新界面
  },
  get: { 获取数据 },
};

1.2 View 视图层
//示例
let View={
    el:要刷新的元素,
    html:'要显示在页面上的刷新内容'
    init(){
        v.el:初始化需要刷新的元素
    }render(){
        刷新页面
    }
}

1.3 Controller 控制器

控制器就是通过绑定事件,根据用户的操作,调用 M 和 V 更新数据和视图

let Controller={
    init(){
        v.init()//初始化View
        v.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=新数据
        m.update(data) // controller 通知 model去更新数据
    },
    autoBindEvents(){
        for (let key in c.events) { // 遍历events表,然后自动绑定事件
      const value = c[c.events[key]]
      const spaceIndex = key.indexOf(' ')
      const part1 = key.slice(0, spaceIndex) // 拿到 'click'
      const part2 = key.slice(spaceIndex + 1)  // 拿到'#add1'
      v.el.on(part1, part2, value)
    }
}

二、EventBus

2.1 EventBus 是什么?

EventBus 主要用于对象之间的通信,比如在上面的例子中,Model 数据模型 和 View 视图模型彼此不知道彼此的存在,但是又需要通信,于是就要用到 EventBus总结:使用 eventBus 可以满足最小知识原则,m 和 v 互相不知道对方的细节,但是却可以调用对方的功能

2.2 EventBus 有哪些 API?

eventBus 提供了 on、off 和 trigger 等 API,on 用于监听事件,trigger 用于触发事件
比如在上面的 MVC 模型中, M 数据模型更新时,会 trigger 触发一个事件。

const m = {
  ....
  update(data) {
    Object.assign(m.data, data)
    eventBus.trigger('m:updated')  // 通知一下view层,我已经更新了数据,view该开始工作了
    localStorage.setItem('n', m.data.n)
  },
  ....
}

然后在 controller,controller 会用 on 监听事件, 然后通知 view 模型去重新渲染页面

const c = {
  init(container) {
    v.init(container)
    v.render(m.data.n) // view = render(data)
    c.autoBindEvents()
    eventBus.on('m:updated', () => {   // controller会用 on  监听事件,
      //然后通知 view 模型去重新渲染页面
      console.log('here')
      v.render(m.data.n)
    })
  },
  ...
}

三、表驱动编程

当我们需要判断 3 种以上的情况,做出相应的事情,往往需要写很多很多的 If else,这样的代码可读性不强, 为了增强代码的可读性,我们可以用表驱动编程,把用来做 If 条件判断的值存进一个哈希表,然后从表里取值

举例:
在上面的例子中,加减乘除四个按钮我需要分别判断是哪一个按钮被点击,再修改 output 的值,按照传统做法, 我们会对四个按钮分别绑定 click 事件,然后再分别写四个回调函数,修改值

$button1.on('click', () => {
    let n = parseInt($number.text())
    n += 1
    localStorage.setItem('n', n)
    $number.text(n)
})

$button2.on('click', () => {
    let n = parseInt($number.text())
    n -= 1
    localStorage.setItem('n', n)
    $number.text(n)
})

$button3.on('click', () => {
    let n = parseInt($number.text())
    n = n * 2
    localStorage.setItem('n', n)
    $number.text(n)
})

$button4.on('click', () => {
    let n = parseInt($number.text())
    n = n/2
    localStorage.setItem('n', n)
    $number.text(n)
})

--------用事件委托后-------
  const c = {
    init(container) {
        v.init(container)
        v.render(m.data.n)
        c.BindEvents()
    }
    BindEvents() {
        v.el.on('click', '#add1', () => {
            m.data.n += 1
            v.render(m.data.n)
        })
        v.el.on('click', '#minus1', () => {
            m.data.n -= 1
            v.render(m.data.n)
        })
        v.el.on('click', '#mul2', () => {
            m.data.n *= 2
            v.render(m.data.n)
        })
        v.el.on('click', '#divide2', () => {
            m.data.n /= 2
            v.render(m.data.n)
        })
    }
}

但是这样太麻烦了,更新措施:1. 绑定加减乘除按钮的父元素,就只用一个事件监听器 2.用哈希表存下按钮和按钮对应的操作

const c = {
  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 (let key in c.events) {
      const value = c[c.events[key]]
      const spaceIndex = key.indexOf(' ')
      const part1 = key.slice(0, spaceIndex)
      const part2 = key.slice(spaceIndex + 1)
      v.el.on(part1, part2, value)
    }
  }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值