M
Model(数据模型),负责操作所有数据
const m = {data: {n: parseInt(localStorage.getItem('n'))},//获取数据create() {},//增delete() {},//删update(data) {Object.assign(m.data, data)eventBus.trigger('m:updated')localStorage.setItem('n', m.data.n)},//改get() {}}//查}
V
View(视图),负责所有UI界面
const v = {el: null,//接受一个容器html: `//生成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) {v.el = $(container)},//初始化容器render(n) {if (v.el.children.length !== 0) v.el.empty()$(v.html.replace('{{n}}', n)).appendTo(v.el)}//通过if else判断容器的后代是否存在进行增删,最后渲染到页面}
C
Controller(控制) 负责其他
const c = {//初始化容器init(container) {v.init(container)v.render(m.data.n) // view = render(data)c.autoBindEvents()//自动绑定事件eventBus.on('m:updated', () => {console.log('here')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
EventBus
主要用于组件/对象间通信的优化和简化
常用API有:on、trigger、off
on:监听数据的变化,如果数据有变化,直接render(再次将变化后的数据渲染到页面)this.on('m:updated', () => {this.render(this.data)})
tirgger:自动触发事件update(data) {Object.assign(m.data, data)//把传进来的data直接放在m.data上eventBus.trigger('m:updated')//通过trigger自动更新数据localStorage.setItem('n', m.data.n)//储存数据
off:关闭的意思
表驱动
通过哈希表将事件抽象出来,简化了代码,降低了重复率,这就是表驱动。
对模块化的理解
先说说如果没有模块化,那么前端代码会是怎样的情况:
- 变量和函数不易维护,容易污染全局作用域
- 加载资源的方式通过script标签从上到下
- 大型项目资源难易维护
在较大的项目中使用模块化可以给我们带来很多好处,比如:
- 解决命名冲突
- 提高代码复用性
- 提高代码可维护性
- 代码之间的耦合度低
- 多人协作互不干扰
