设计模式
官方一点的解释:设计模式是一套被反复使用的、多数人知晓的、经过分类编目的、代码设计经验的总结
emmmmmm 浅显一点理解就是对通用代码写法模式取个名字
MVC
M(Model)
模型层,用于封装与应用程序的业务逻辑相关的数据以及对数据的处理方法
V(View)
视图层,界面设计人员进行图形界面设计,是用户看到并与之交互的界面
C(Controller)
控制层,连接视图和模型桥梁,处理业务逻辑操作,根据视图层输入的指令,选取模型层数据,进行相应操作整合将结果反馈给视图层
用一个简单的计算器为例
Model / View / Controller 伪代码
// Model.js
Model = {
data: { /* 程序需要操作的数据或信息 */ },
create: { /* 增数据 */ },
delete: { /* 删数据 */ },
update(data) {
Object.assign(m.data, data) //使用新数据替换旧数据
eventBus.trigger('m:upate') // eventBus触发'm:update'信息, 通知View刷新
},
get:{ /* 获取数据 */ }
}
// View.js
View = {
el: /* 需要刷新的元素 */,
html: `显示在页面上的内容`
init(){
v.el: /* 需要刷新的元素 */
},
render(){ /* 刷新页面 */ }
}
// Controller.js
Controller = {
init(){
v.init() // View初始化
v.render() // 第一次渲染
c.autoBindEvents() // 自动的事件绑定
eventBus.on('m:update', () => { v.render() }) // 当eventBus触发'm:update'时View刷新
},
events:{ /* 事件以哈希表方式记录 */ },
method() {
data = /* 改变后的新数据 */
m.update(data)
},
autoBindEvents() { /* 自动绑定事件 */ }
}
抽象思维
最小知识原则
需要知道的知识越少越好
例子 🌰
// XXX.js
import 'XXX.css' // 导入样式文件
const html = `<div>页面要写的内容</div>`
/* 其他代码 */
在 .html
文件中引入这个 .js
文件(下面‘模块’指这个 .js
文件)即可获得这个模块有关的 Dom 元素、样式和行为,对于 .html
文件而言不需要再引入一个相关的样式文件,并且也不需要编写这个模块所需的 Dom 结构
这样做会使得页面一开始是空白的,可以用加菊花图、加骨架、加占位内容等方法解决
以不变应万变
既然 MVC 模式可以适用每个模块的写法,那就每个模块都这样写好了(这里需要两个例子对比)
代价是有时候会有一些多余不用的代码
表驱动编程
表驱动编程是指将重要的信息存储在哈希表中,利用表来编程简化重复的代码,从而不必使用很多的逻辑(if 或 switch)语句
在上例中 c 对象的 events 属性就是一个哈希表
events: {
'click #add1': 'add',
'click #minus1': 'minus',
'click #mul2': 'mul',
'click #divide2': 'div',
}
当触发点击事件的对象是#add1时则执行add函数,代码效果等同于直接在#add1元素上绑定click事件执行add函数。当在事件类型或监听对象多时使用哈希表的优点就更加明显:代码复杂度稳定更易于理解
事不过三
“重复即是原罪”
同样的代码写三遍,就应该抽离成一个函数
同样的属性写三遍,就应该做成共有属性(原型或类)
同样的原型写三遍,就应该用继承
俯瞰全局
把所有的对象看成点
一个点和一个点怎么通信
一个点和多个点怎么通信
多个点和多个点怎么通信
找出一个专用的点 EventBus(事件总线)负责通信
EventBus 主要用于对象间的通信。如上例中通过定义一个 jQuery 包装的 window 对象获取 jQuery 方法,如 on()
、 trigger()
等。
view = render(data)
通过 render 改变视图,只要改变data,就可以得到对应的view, 使用虚拟 DOM 能让 render 只更新该更新的地方,从而解决性能问题