为什么有设计模式
Don't repeat yourselt
重复
代码级别的重复
页面基别的重复
MVC
- M - Model (数据模型) 负责操作所有数据
- V - View(试图) 负责所有UI界面
- C - controller(控制器) 负责其他
经典MVC中,一对controller-view捆绑起来表示一个ui组件,controller直接接受用户输入,并将输入转为相应命令来调用model的接口,对model的状态进行修改,最后通过观察者模式对view进行重新渲染。
以下为大体逻辑。
// model层负责存储数据以及数据更新
const model = {
data: {
// 存放数据
},
// 不同的触发事件
update(){},
destroy(){},
get(){},
insert(){},
}
// view 层负责数据渲染
const view = {
el: null,// 存储挂载对象
init: function(){},//初始化view
template: ``,//html模板
render: (){}//重新渲染视图
}
// controller 层控制操作model层,并通过model层事件触发view层的渲染
const controller = {
events: {}// 存储事件
init(){
// 初始化view层
view.init();
// 渲染view
view.render();
// 视图监听model的数据变更
listener();
},//初始化数据
}
eventBus
实现了类似于发布订阅者模式的功能,可以理解为,你订阅了晨报,每天会有人向你推送晨报。
on
进行事件的监听
eventBus.on( 事件名, 事件)
trigger
触发的监听的事件
eventBus.trigger(事件名)
表驱动编程
更像使用枚举。
let enum = {
"car": function(){
console.log("开车去兜风");
},
"food": function(){
console.log("充饥")
}
},
const any = "car";
enum[any]()//执行car
模块化
背景
我们现在有了运行大量 Javascript 脚本的复杂程序,还有一些被用在其他环境。
有必要开始考虑提供一种将 JavaScript 程序拆分为可按需导入的单独模块的机制。
代码分割
通过对内容或者模块进行划分,实现内容的解耦,如果部分功能出现问题,但是不会影响整体效果。并且,由于代码的分割,使得模块被替换时更加容易。
导出
采用export的方法到处,那么应该使用以下代码:
export const name = 'square';
导入
我们采用import的方法,导入文件代码如下
import { name} from '文件';
动态模块加载
这允许您仅在需要时动态加载模块,而不必预先加载所有模块。
import('/modules/myModule.mjs')
.then((module) => {
// Do something with the module.
});
抽象思维
最小知识原则
- 引入一个模块需要引入html、css、js
- 引入一个模块需要引入html、js
- 引入一个模块需要引入js
你需要知道的越少越好,模块化为这一点奠定了基础
代价
- 这样做会使得页面一开始就是空白的,没内容没样式
- 解决方法,如:loading加载效果
- 采用ssr技术
抽象思维2
以不变应万变
- 每个模块都使用m+v+c搞定
代价
- 有时候会有一些冗余代码
- 无法变通
抽象思维3
表驱动编程
- 看到大量类似重复代码
- 把重要数据做成哈希表
缺点
- 无
抽象思维4
事不过三
- 同样的代码写三遍,就应该抽成一个函数
- 同样属性写三遍,就应该做成公用属性(原型或者类)
- 同样的原型写三遍,就应该用继承
缺点
- 有的时候会造成继承层级太深,无法一下看懂代码
- 可以通过写文档、画类图解决
抽象思维5
俯瞰全局
- 把所有的对象看成点
- 一个点和一个点怎么通信
- 一个点和多个点怎么通信
- 多个点和多个点怎么通信
- 找出一个专用的点负责通信
- 这个点就是event bus(事件总线)
抽象思维6
view = render(data)
- 比起操作DOM对象,直接render简单多了
- 只要改变data,就可以得到对应的view
缺点
- render 粗犷的渲染肯定比DOM操作浪费性能
- 虚拟DOM可以让render只更新该更新的地方