浅析MVC

定义

设计模式就是–某个人觉得自己写的代码太漂亮了,觉得别人肯定也用得到
于是就给这种代码取了个名字并分享出来— — 设计模式就是对通用代码取名字

为什么要有设计模式

don’t Repeat Yourself — DRY原则 (不要重复你自己)

代码级别的重复

把相同的三行代码写了两遍— — 那么就应该重构它

页面级别

你把类似的页面做了10遍— — 那么你就应该想出一个万金油的写法

MVC就是一个万金油

所有的页面都可以使用MVC来优化代码结构

不学MVC会怎么样

  • 写出一手又臭又长的代码
  • 不停重复代码,不懂得抽象
  • 只会调用API,不能提升自己
  • 只会写业务,不会封装,更不会造轮子

MVC是什么

每个模块都可以携程三个对象,分别是M,V,C
M — Model(数据模型) 负责操作所有数据

//数据相关都放m
const eventBus = $(window)
const m = {
    data:{
      n:parseFloat(localStorage.getItem('n'))//数据源
    },
    create(){
      //增加数据
    },
    delete(){
      //删除数据
    },
    update(data){
      Object.assign(m.data,data)    //用新数据替换旧数据
      eventBus.trigger('m:updated')  //eventBus触发'm:updated'信息,通知View刷新界面
      localStorage.setItem('n', m.data.n)
    },
    get(){
      //获取数据
    }
}

V — View(视图) 负责所有UI界面
在整个MVC架构中用户唯一可以看到的一层,接收用户的输入,显示处理结果。

//视图相关都放v
const v = {
    el:要刷新的元素,
    html:`要显示在页面上的刷新内容`,
    init(){
        v.el:初始化需要刷新的元素
    },
    render(){
       // 刷新页面
    }
}

C — Controller(控制器) 负责其他
控制器就是通过绑定事件,根据用户的操作,调用Model和View更新数据和视图

//其他都放c
const eventBus = $(window)
const c = {
    init(){
        v.init()   //初始化View
        v.render()  //第一次渲染页面
        c.autoBindEvents()  //自动的事件绑定
        eventBus.on('m:update',()=>{v.render()} //当eventBus触发'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)
    }
}

MVC没有严格的定义,是一个抽象概念

抽象思维

1、最小知识原则

引入一个模块需要引入 html、css、js
引入一个模块需要引入 html、js
引入一个模块需要引入 js
你需要知道的知识越少越好
模块化为这一点奠定了基础
代价
这样做会使得页面一开始是空白的,没内容没样式
解决方法很多,比如加菊花、加骨架、加占位内容等
也有人选择用 SSR 技术来解决,个人觉得没必要

2、以不变应万变

既然每个模块都可以用 m + v + c 搞定
那么每个模块我就都这样写就好啦
不用再思考类似的需求该怎么做了
代价
有时候会有一些多余的用不到代码
有时候遇到特殊情况不知道怎么变通,比如没有 html 的模块怎么做 mvc

3、事不过三

同样的代码写三遍,就应该抽成一个函数
同样的属性写三遍,就应该做成共用属性(原型或类)
同样的原型写三遍,就应该用继承
代价
有的时候会造成继承层级太深,无法一下看懂代码
可以通过写文档、画类图解决

4、eventBus

把所有的对象看成点
一个点和一个点怎么通信
一个点和多个点怎么通信
多个点和多个点怎么通信
最终我们找出一个专用的点负责通信 这个点就是
event bus(事件总线)

模块通信
解决模块之间通信的问题,view组件层面,父子组件、兄弟组件通信都可以使用eventbus处理
模块解耦
storage change事件,cookie change事件,view组件的事件等,全部转换
使用Event Bus来订阅和发布,这样就统一了整个应用不同模块之间的通信接口问题。
父子页面通信

window.postMessage + Event Bus

多页面通信

storage change + Event Bus

EventBus的一些常用api

on(监听事件)
trigger(触发事件)
off(取消监听)

eventBus.trigger('m:updated') // 触发事件,大叫'm 已经更新了'
eventBus.on('m:updated', () => { console.log('here') }) '监听事件,听到后执行函数'

5、view = render(data)

react就是这一思想的实践框架,vue是局部渲染
比起操作 DOM 对象,直接 render 简单多了
只要改变 data,就可以得到对应的 view
代价
render 粗犷的渲染肯定比 DOM 操作浪费性能
还好我们后面会用到虚拟 DOM
虚拟 DOM 能让 render 只更新该更新的地方

6、表驱动编程

将类似不重复的代码,筛选出重要的数据抽离成哈希表结构
当有大批类似但不重复的代码
筛选重要的数据
把重要的数据做成哈希表,代码就简单了
代价
没有代价

// 举个栗子
events:{  // 事件集合的哈希表
   'click #app1': 'a操作''click #app2': 'b操作''click #app3': 'c操作''click #app4': 'd操作'} 
autoBindEvents() { // 通过哈希变自动绑定事件
    for ( let key in c.events) {
        if ( c.events.hasOwnProperty(key) ) {
            const spaceIndex = key.indexOf(' ')   // 找到'click #app1'空格的数组下标
            const part1 = key.slice(0, spaceIndex) // 通过spaceIndex 分割 'click' 和 '#app1'
            const part2 = key.slice(spaceIndex + 1)
            const value = c[c.events[key]]
            v.el.on(part1, part2, value)  // 自动把多个事件绑定在一个元素上
        }
    }
}
// 如何一来在稳定的复杂度里,可以绑定多个事件

模块化

类什么时候用

继承什么时候用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Supernova_gu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值