你可以看到的:
MVC
EventBus
表驱动编程
我对模块化的理解
源码:https://github.com/woshidw/mvc-demo-1
--资料来源于饥人谷
什么是MVC
MVC是出名的设计模式,所有的页面都可以使用 MVC来优化代码结构。页面可以分为很多模块,每个模块都可以写成三个对象,分别是M、V、c
MVC三类对象
MVC模式(Model-view-controller) 是一种设计模式(软件架构)。
MVC包括三类对象,将它们分离以提高灵活性和复用性。
- 模型(Model) : 同于数据管理, 一旦模型的数据发生改变,Model将通知有关的视图。
- 视图(View) : 负责用户界面,HTML渲染。 描绘的是Model的当前状态,当模型的数据发生改变,View就会刷新自己。
- 控制(Controller) : 控制器, Controll 控制其他所有流程。 负责监听并处理视图(View)的事件。更新和调用Model。也负责监听Model的变化,并更新View。
const m = {
data: {
index: parseInt(localStorage.getItem(localKey)) || 0
},
create() {},
delete() {},
update(data) {
Object.assign(m.data, data)
eventBus.trigger('m:updated')
localStorage.setItem('index', m.data.index)
},
get() {}
}
由于M是负责操作数据的,我们将我们所需要的变量index存入到了m对象中,这就是Model
const v = {
el: null,
html: (index) => {
return `
<div>
<ol class="tab-bar">
<li class="${index === 0 ? 'selected' : ''}" data-index="0"><span>1111</span></li>
<li class="${index === 1 ? 'selected' : ''}" data-index="1"><span>2222</span></li>
</ol>
<ol class="tab-content">
<li class="${index === 0 ? 'active' : ''}">内容1</li>
<li class="${index === 1 ? 'active' : ''}">内容2</li>
</ol>
</div>
`
},
init(container) {
v.el = $(container)
},
render(index) {
if (v.el.children.length !== 0) v.el.empty()
$(v.html(index)).appendTo(v.el)
}
}
由于V是负责操作视图的,我们将所需要的添加的html文件以及渲染的函数封装到了V对象中
const c = {
init(container) {
v.init(container)
v.render(m.data.index) // view = render(data)
c.autoBindEvents()
eventBus.on('m:updated', () => {
v.render(m.data.index)
})
},
events: {
'click .tab-bar li': 'x',
},
x(e) {
const index = parseInt(e.currentTarget.dataset.index)
m.update({index: index})
},
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)
}
}
}
C代表的是其他的一些操作,这里放入了绑定事件,以及初始化事件。
我们要用最小知识原则
最小知识原则
引入一个模块需要引入 html、css、js
引入一个模块需要引入 html、js
引入一个模块需要引入 js
你需要知道的知识越少越好
模块化为这一点奠定了基础
用模块化用户只会看到一个js的文件,其他的文件都被我们通过export import 导入导出的方式放到了我们的js代码中,即可实现网页的展示
大家可以清晰的看到,我们将每一个部分都各自的抽成了一个模块,当我们需要改动数据,或者需要修改绑定事件时只需要去对应的位置进行修改即可,这就是MVC设计模式
EventBus
- 比如用vue, new一个新的vue,它是一个实例对象。
- 但是最重要的在于它原型上有我们用到的on(监听)、on(监听)、on(监听)、off(解绑)、$emit(触发)等API 。
EventBus作用:
- EventBus 主要用于对象间的通信,
- 使用 EventBus 可以满足最小知识原则,model和view互相不知道对方的细节,但是却可用调用对方的功能。
const eventBus = $(window)
eventBus.trigger('m:update') // 自动触发事件update
eventBus.on('m:update', () => {console.log('触发';)}) //监听事件 然后执行函数
表驱动编程
当我们需要判断 3 种以上的情况,做出相应的事情,往往需要写很多很多的 if else,这样的代码可读性不强。
为了增强代码的可读性,我们可以用表驱动编程,把用来做 if 条件判断的值存进一个哈希表,然后从表里取值。
而这种做法的意义就在于: 逻辑和数据是分离的
举个例子,比如国家简写转换,给一个国家全名,转换成国家简写,用if else语法来写:
// 伪代码
function contry(国家名){
if(中国){
return "CHN"
}else if(日本){
return "JPN"
}else if(美国){
return "USA"
}else{
return "OTHER"
}
}
用 if else语句这样做,如果我再增加一个国家,那么就要写一个if else语句。等于又增加了一条逻辑。
那么我们为何不用 表数据编程 把 数据和逻辑分离开实现呢。
毕竟,数据的添加是简单,低成本和低风险的。 而逻辑的添加是负责,高成本和高风险的。
表驱动编程做法:
伪代码
function contry(国家名){
const 国家列表 = [
"中国" = "CHN"
"日本" = "JPN"
"美国" = "USA"
]
国家简写转换:funciton(){
for(let 国家名 in 国家列表){
return 国家列表[国家名] // 返回的就是 国家简写
}
}
}
这样做的话,如果再添加一个国家名(数据),那么我们只需国家列表(数组)中添加一项即可。逻辑方面的我们一点都不需要更改,更别说去考虑逻辑了。
这样,我们就脱离了数据与逻辑的关系了。
**
参考文章: 用表驱动编程重构if-else的意义
如何理解模块化
将一个复杂的程序依据一定的规则(规范)封装成几个块(文件)并进行组合。
模块的内部数据的实现是私有的,只是向外部暴露一些接口(方法)与外部其他模块通信。这则就是模块化。
好处:
- 降低代码耦合度
- 减少重复代码
- 提高代码重用性
- 在项目结构上更加清晰,便于维护。
若在模块中我们都采用的是jquery的库,若以后公司不使用该库,我们可以直接修改对应的模块即可,倘若全都在一个js文件中,极其的不利于我们的修改,同时还增加了我们对代码的复用性,若有哪个地方需要用到一个独立的类,或者方法直接import导入即可使用