设计模式

在讲述MVC之前,我们先来了解下什么是“设计模式”?

通俗的来讲就是有一个程序员写了一份代码,他觉得自己写的非常好,可以供他人借鉴,于是就对这种写法取一个名字,比如”适配器模式“。“设计模式”就是对通用代码取一个名字而已。

为什么要有设计模式呢?

为了不让你重复你自己(Don't Repeat Yourself - DRY 原则)


什么是MVC?

如何设计一个程序的结构叫做"架构模式"(architectural pattern)。MVC模式就是架构模式的一种,它对我后面框架的学习启发很大。我觉得这种模式也可以应用于其他领域。

下面是我个人对MVC模式的一些个人理解,有的地方不一定真确,仅供思路理解作参考。

提问:你见过面条式代码吗?什么样的代码是面条式的?

比如像下面这种代码:

$("button").prop("disabled", true)
$("textarea").on("input", function() {if ($(this).val().length > 0) {$("button").prop("disabled", false)} else {$("button").prop("disabled", true)}
})

你如果不学MVC,你将写出面条式的烂代码。不停的重复自己、不懂得抽象思维、只会调API、不懂封装、不会造轮子,不能提升自己!!!

讲了这么多,就是希望你能学习MVC设计模式,对你以后的发展会有更大的帮助。

MVC定义:MVC分别是Model(模型)、View(视图)和Controller(控制)。该模式认为,无论你的程序多么简单或复杂,从结构上看,都可以分成三层。

  • Model(模型):负责操作所有数据
  • View(视图):负责所有 UI 界面
  • Controller(控制):负责其它相应操作

这三层是紧密联系在一起的,但又是互相独立的,每一层内部的变化不影响其他层。每一层都对外提供接口,供上面一层调用。这样一来,软件就可以实现模块化,修改界面或者变更数据都不用修改其他层,大大方便了维护和升级。


下面请看<代码一>→<代码二>的抽离过程

代码一:

//初始化html
const html = `
<div><div class="output"><span id="number">{{n}}</span></div><div class="actions"><button id="add1">+1</button><button id="minus1">-1</button><button id="mul2">*2</button><button id="divide2">÷2</button></div>
</div>
`
const $element = $(html).appendTo($('body').page)
//获取元素
const $button1 = $('#add1')
const $button2 = $('#minus1')
const $button3 = $('#mul2')
const $button4 = $('#divide2')
const $number = $('#number')
//初始化数据
const n = localStorage.getItem('n')
//将数据渲染到页面
$number.text(n || 100)
//绑定鼠标事件
$button1.on('click', () => {let n = parseInt($number.text())n += 1localStorage.setItem('n', n)$number.text(n)
})
$button2.on('click', () => {let n = parseInt($number.text())n -= 1localStorage.setItem('n', n)$number.text(n)
})
$button3.on('click', () => {let n = parseInt($number.text())n *= 2localStorage.setItem('n', n)$number.text(n)
})
$button4.on('click', () => {let n = parseInt($number.text())n /= 2localStorage.setItem('n', n)$number.text(n)
})

代码二:

const eventBus = $(window)    //拥有.on(监听事件)函数/.trigger(触发事件)函数
// 数据相关都放到M
const m = {data: {n: parseInt(localStorage.getItem('n'))//初始化数据},create() {},delete() {},update(data) {Object.assign(m.data, data)eventBus.trigger('m:updated')//m跟新了,会触发(事件不能有空格)localStorage.setItem('n', m.data.n)},get() {}
}
// 视图相关都放到V
const v = {el: null,html: `<div><div class="output"><span id="number">{{n}}</span></div><div class="actions"><button id="add1">+1</button><button id="minus1">-1</button><button id="mul2">*2</button><button id="divide2">÷2</button></div></div>
`,init(container) {//外面传入containerv.el = $(container)},render(n) {if (v.el.children.length !== 0) v.el.empty()$(v.html.replace('{{n}}', n)).appendTo(v.el)}
}
// 其他都C
const c = {init(container) {//初始化v.init(container)v.render(m.data.n) // view = render(data)c.autoBindEvents()eventBus.on('m:updated', () => {//监听数据变化,然后渲染v.render(m.data.n)})},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)}}
}
export default c

从代码一到代码二,你会发现变复杂了,像代码1那样写的多清楚明了,代码2这里那里的,都绕晕了。。。那是你还没有发现MVC的好处。

在代码2中,所有的属性都是经典的、缺一不少的,你可以在任何地方使用(万金油),代码2在代码1的基础上进行了抽象的转化,代码的简化,看起来复杂了,实际上变得简单可复用了。

EventBus 对象间的通信

jQuery中有一个.on()和.trigger()方法,分别用来监听和触发。如果我在一个地方监听事件,一个地方触发事件,那么这两处不是实现了通信吗。 jQuery API具体实现

用法:

  $( "p" ).on( "myEvent", function( event, param ) {console.log(param)})$( "p" ).trigger( "myEvent", [ "123" ] )

下面我们自己实现eventButs(借用了jQuery)

import $ from 'jquery'
class EventButs {constructor() {this._eventBus = $(window)}//监听函数on(eventName, fn) {return this._eventBus.on(eventName, fn)}//触发函数trigger(eventName, data) {return this._eventBus.trigger(eventName, data)}//取消监听off(eventName, fn) {return this._eventBus.off(eventName, fn)}
}
export default EventButs const e = new EventButs ()
e.on()
e.trigger()
e.off()

表驱动编程

定义:当你看到大批类似但不重复的代码时,你需要看看到底哪些才是重要的数据,把重要的数据做成哈希表,你的代码就简单了。

下面的代码可以使用哈希表简化:

bindEvents() {v.el.on('click', '#add1', () => {m.data.n += 1v.render(m.data.n)})v.el.on('click', '#minus1', () => {m.data.n -= 1v.render(m.data.n)})v.el.on('click', '#mul2', () => {m.data.n *= 2v.render(m.data.n)})v.el.on('click', '#divide2', () => {m.data.n /= 2v.render(m.data.n)})
}

简化后的:

const c = {init(container) {//初始化v.init(container)v.render(m.data.n) // view = render(data)c.autoBindEvents()eventBus.on('m:updated', () => {//监听数据变化,然后渲染v.render(m.data.n)})},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)}}
}

的mvc_浅谈MVC相关推荐

  1. 浅谈 MVC、MVP 和 MVVM 架构模式

    2019独角兽企业重金招聘Python工程师标准>>> 谈谈 MVX 中的 Model 谈谈 MVX 中的 View 谈谈 MVX 中的 Controller 浅谈 MVC.MVP ...

  2. 浅谈MVC Form认证

    简单的谈一下MVC的Form认证. 在做MVC项目时,用户登录认证需要选用Form认证时,我们该怎么做呢?下面我们来简单给大家说一下. 首先说一下步骤 1.用户登录时,如果校验用户名密码通过后,需要调 ...

  3. 浅谈MVC设计模式和SSH框架的关系

    一.MVC:是指Model-View-Controler,是程序的一种分层模式,是一种思想. MVC是Model-View-Controler的简称.即模型-视图-控制器.MVC是一种设计模式,它强制 ...

  4. 浅谈MVC MVP MVVM

    复杂的软件必须有清晰合理的架构,否则无法开发和维护. MVC(Model-View-Controller)是最常见的软件架构之一,业界有着广泛应用. 它本身很容易理解,但是要讲清楚,它与衍生的 MVP ...

  5. 浅谈MVC、MVP、MVVM架构模式的区别和联系

    MVC.MVP.MVVM这些模式是为了解决开发过程中的实际问题而提出来的,目前作为主流的几种架构模式而被广泛使用. 一.MVC(Model-View-Controller) MVC是比较直观的架构模式 ...

  6. 浅谈 MVC与三层架构

    引言: 使用Eclipse开发工具写Java Web项目时会发现,一个中型或者大型项目 随着代码的增多,会发现:代码既可以写在src目录下,也可以写在WebContent目录下.src下可以建很多包 ...

  7. 浅谈MVC三层架构(通俗易懂)

    "怕什么真理无穷,进一寸有一寸的欢喜"        ----胡适 什么是MVC三层架构? 所谓MVC三层架构,指的是Model View Controller,即模型.视图.控制 ...

  8. php smarty 原理,php模板原理PHP模板引擎smarty模板原理浅谈

    mvc是开发中的一个伟大的思想,使得开发代码有了更加清晰的层次,让代码分为了三层各施其职.无论是对代码的编写以及后期的阅读和维护,都提供了很大的便利. 我们在php开发中,视图层view是不允许有ph ...

  9. 浅谈Spring MVC知识

    关于MVC框架,我相信大家都不陌生,都会说也就是模型-视图-控制器这三层的框架结构,如果你参加面试的时候考官会问:"MVC框架是什么?你说一说."其实我们都知道这个问题还需要问的, ...

最新文章

  1. 字节跳动招聘2年工作经验:30-60k!什么岗位这么香?
  2. centos7升级python到3_CentOS7 升级Python2.x到3.x
  3. 【POJ - 2965】The Pilots Brothers' refrigerator(暴力枚举,思维)
  4. video js 全屏时,遇到18:9的长屏幕时,画面被切割
  5. opencv 图像处理应用之车道检测
  6. 【MATLAB】通信信号调制通用函数 — 带通滤波器
  7. pbs分解_谈WBS与PBS
  8. spring三级缓存
  9. 度度熊保护村庄 HDU - 6080 floyd最小环/叉积判左右
  10. 【SpringBoot教程】根据环境自动装配
  11. 做读书笔记好用的软件分享
  12. python三大框架_python 三大框架的 介绍。
  13. ALV字段目录lvc_s_fcat
  14. 同步升压与非同步升压区别
  15. 阿里云服务器怎么样?详细介绍
  16. 使用延时队列搞定超时订单处理
  17. Boring Old Menu Bar for Mac(菜单栏美化工具)
  18. 理解torch.einsum(‘ijk,ilk->ijl‘, a,b)
  19. 在iOS设备中跑Python脚本
  20. 计算机网络中 冲突域、广播域

热门文章

  1. 基于JAVA+Servlet+JSP+MYSQL的新闻发布系统
  2. 基于JAVA+SSH+MYSQL的大学生入学注册自助系统
  3. php 是面向对象编程,PHP面向对象编程快速入门
  4. java6 3_2018.3.6 Java web notes:
  5. jedis操作set_你真的会使用redis的数据类型set么
  6. 如何在C#中使用全局鼠标、键盘Hook
  7. LeetCode Length of Longest Fibonacci Subsequence
  8. 通过fork进程爆破canary
  9. window.location.href重定向 不会触发webview
  10. Linux的watch命令 -- 实时监测命令的运行结果