模块化、MVC化、对象化、类化
简介
记录由一坨很乱的代码到很简洁有条理的代码的过程。
很乱的代码–>模块化–>MVC化–>对象化–>类化
代码
代码范围:从 模块化
到 message的类化
1.很乱的一坨代码
简述
一坨代码写在一起,各种全局变量,容易互相覆盖,而且代码很乱,没条理。
关键
变量 + 函数 + 函数调用
模块化
简述
把一堆各种功能的代码分成各种js文件,例如:run.js、print.js,每个js文件用立即执行函数实现局部变量。
关键
立即执行函数
代码
index.html
<script src="run.js"></script>
<script src="print.js"></script>
print.js
! function () {
// 原本功能的代码
var abc = 100
function hehe() {
console.log(abc += 1)
}
hehe()
}.call()
2.模块之间沟通共享
简述
多个模块之间可能需要互相沟通数据,此时需要通过闭包实现。
关键
闭包
代码
闭包
// 闭包
function bibao() {
var abc = 100
function hehe() {
console.log(abc += 1)
}
return hehe
}
// 其他人使用这个闭包。能用hehe函数给abc+1,但是完全不知道abc的值。
var usebibao = bibao()
usebibao()
立即执行函数+闭包
! function () {
var abc = 100
window.hehe = function () {
console.log(abc += 1)
}
}.call();
// 其他人能使用window.hehe函数给abc+1,但是完全不知道abc的值。
window.hehe()
3.vc化
简述
引入MVC思想,使得代码更有组织,但是前端在没有操作数据时,Model是没有的,所以VC化很常见。
关键
把代码归类,html相关的基本属于view,剩下的就是controller。
代码
! function () {
var view = document.querySelector('.className')
var controller = function (view) {
var viewSon = view.querySelector('.className')
console.log(view)
console.log(viewSon)
}
controller(view)
}.call()
4.对象化
简述
把代码对象化。
关键
把相关的函数、变量挂到controller的属性。
注意:使用this要注意this被监听函数修改为触发事件的对象,可以用箭头函数修正,箭头函数的this会就进取。
代码
! function () {
var view = document.querySelector('.className')
var controller = {
view: null,
viewSon: null, // viewSon是saySon函数需要的,也要初始化
init: function (view) {
this.view = view
this.viewSon = this.view.querySelector('.className')
this.hehe()
this.saySon()
},
hehe: function () {
var view = this.view
console.log(view)
},
saySon: function () {
console.log(this.viewSon)
},
}
controller.init.call(controller, view)
}.call()
// 运行过程:
// 1.controller.init.call(controller, view) 把controller和外面的变量view传进init函数里去
// 2.this.view = view 把变量view赋值给controller.view
// 3.this.hehe() 把controller传进hehe函数里去
// 4.var view = this.view 声明一个view变量,controller.view赋值给这个变量
// 5.console.log(view) 把view打印出来。
// 整个过程中 this 一直都是controller,
// 外面的变量view赋值给了controller.view
// controller.view又赋值给了hehe函数里新声明的view
// 最后console.log(view)把hehe函数里的view打印出来
// 写法流程:
// 1.把controller写成一个对象
// 2.controller需要一个view、init、执行函数hehe
// 3.init把需要执行的函数hehe和view关联起来
// 4.init调用,把外面的view交给controller,并调用hehe函数,hehe函数就运行成功
5.MVC化
简述
对于有数据操作的代码,还要在VC化的基础上,把M分离出来。
关键
一般VC化后,从controller里把数据相关的函数拿出来放进Model里就行了。
注意:使用this要注意this被监听函数修改为触发事件的对象,可以用箭头函数修正,箭头函数的this会就进取。
代码
模块化
// 留言板-模块化.js
! function () {
let messageList = document.querySelector('.messageList')
let postMessageForm = document.querySelector('.postMessageForm')
AV.init({
appId: "XXXXXX",
appKey: "XXXXXX",
});
loadMessage()
bindEvents()
function loadMessage() {
var query = new AV.Query('message');
query.find()
.then(function (message) {
let array = message.map((item) => item.attributes)
array.forEach((item) => {
let li = document.createElement('li')
li.innerText = `${item.name}:${item.content}`
messageList.append(li)
})
})
}
function bindEvents() {
postMessageForm.addEventListener('submit', function (eee) {
eee.preventDefault() // 阻止表单提交默认刷新页面事件
saveMessage()
})
}
function saveMessage() {
let name = postMessageForm.querySelector('input[name=name]').value
let content = postMessageForm.querySelector('input[name=content]').value
// leancloud 提供的保存对象的代码
var Message = AV.Object.extend('message');
var message = new Message();
message.set('name', name);
message.set('content', content);
message.save()
.then(function (object) {
let li = document.createElement('li')
li.innerText = `${object.attributes.name}:${object.attributes.content}`
messageList.append(li)
postMessageForm.querySelector('input[name=content]').value = ''
})
}
}.call()
VC化
// 留言板-VC化.js
! function () {
var view = document.querySelector('.message')
var controller = {
view: null,
messageList: null,
postMessageForm: null,
init: function (view) {
this.view = view
this.messageList = this.view.querySelector('.messageList')
this.postMessageForm = this.view.querySelector('.postMessageForm')
this.initAV()
this.loadMessage()
this.bindEvents()
},
initAV: function () {
AV.init({
appId: "XXXXXX",
appKey: "XXXXXX",
});
},
loadMessage: function () {
var query = new AV.Query('message');
query.find()
.then((message) => {
let array = message.map((item) => item.attributes)
array.forEach((item) => {
let li = document.createElement('li')
li.innerText = `${item.name}:${item.content}`
this.messageList.append(li)
})
})
},
bindEvents: function () {
this.postMessageForm.addEventListener('submit', (eee) => {
eee.preventDefault() // 阻止表单提交默认刷新页面事件
this.saveMessage()
})
},
saveMessage: function () {
let name = this.postMessageForm.querySelector('input[name=name]').value
let content = this.postMessageForm.querySelector('input[name=content]').value
// leancloud 提供的保存对象的代码
var Message = AV.Object.extend('message');
var message = new Message();
message.set('name', name);
message.set('content', content);
message.save()
.then((object) => {
let li = document.createElement('li')
li.innerText = `${object.attributes.name}:${object.attributes.content}`
this.messageList.append(li)
this.postMessageForm.querySelector('input[name=content]').value = ''
})
},
}
controller.init(view)
}.call()
MVC化
// 留言板-MVC化.js
! function () {
var view = document.querySelector('.message')
var model = {
init: function () {
AV.init({
appId: "XXXXXX",
appKey: "XXXXXX",
});
},
fetch: function () {
var query = new AV.Query('message');
return query.find()
},
save: function (name, content) {
var Message = AV.Object.extend('message');
var message = new Message();
message.set('name', name);
message.set('content', content);
return message.save()
},
}
var controller = {
view: null,
model: null,
messageList: null,
postMessageForm: null,
init: function (view, model) {
this.view = view
this.model = model
this.messageList = this.view.querySelector('.messageList')
this.postMessageForm = this.view.querySelector('.postMessageForm')
this.model.init()
this.loadMessage()
this.bindEvents()
},
loadMessage: function () {
this.model.fetch().then((message) => {
let array = message.map((item) => item.attributes)
array.forEach((item) => {
let li = document.createElement('li')
li.innerText = `${item.name}:${item.content}`
this.messageList.append(li)
})
})
},
bindEvents: function () {
this.postMessageForm.addEventListener('submit', (eee)=> {
eee.preventDefault() // 阻止表单提交默认刷新页面事件
this.saveMessage()
})
},
saveMessage: function () {
var name = this.postMessageForm.querySelector('input[name=name]').value
var content = this.postMessageForm.querySelector('input[name=content]').value
// leancloud 提供的保存对象的代码
this.model.save(name, content).then((object) => {
let li = document.createElement('li')
li.innerText = `${object.attributes.name}:${object.attributes.content}`
this.messageList.append(li)
this.postMessageForm.querySelector('input[name=content]').value = ''
})
},
}
controller.init(view, model)
}.call()
6.类化
简述
把MVC化的代码公共部分提取出来,分成3个js文件,其他文件再去使用这3个MVC文件。
关键
1.把公有的代码拿出来做成一个object对象
2.私有的代码作为参数以options对象传进MVC函数
3.object作为this去调用options的私有函数init
4.遍历options的属性拿到其余的属性
5.返回object,它有公有属性,也有私有属性。
代码
以message.js为例。
View.js
// 1.改造前
var view = document.querySelector('.message')
// 私有部分是'.message'
// 2.类化
window.View = function (selector) {
return document.querySelector(selector)
}
// 3.使用方
var view = View('.message')
Model.js
// 1.改造前
var model = {
init: function () {
AV.init({
appId: "mJuVhxO68GtStDWtrhFJUX8t-gzGzoHsz",
appKey: "heQIds6bW7KitjLNGrrYGYv8",
});
},
fetch: function () {
var query = new AV.Query('message');
return query.find()
},
save: function (name, content) {
var Message = AV.Object.extend('message');
var message = new Message();
message.set('name', name);
message.set('content', content);
return message.save()
},
}
// 私有部分是'message'
// 2.类化
window.Model = function (options) {
let resourceName = options.resourceName
return {
init: function () {
AV.init({
appId: "mJuVhxO68GtStDWtrhFJUX8t-gzGzoHsz",
appKey: "heQIds6bW7KitjLNGrrYGYv8",
});
},
fetch: function () {
var query = new AV.Query(resourceName);
return query.find()
},
save: function (object) {// 把原本的name和content合成一个object
var Message = AV.Object.extend(resourceName);
var message = new Message();
message.set('name', object.name);
message.set('content', object.content);
return message.save()
},
}
}
// 3.使用方
var model = Model({resourceName: 'message'})
Controller.js
// 1.改造前
var controller = {
view: null,
model: null,
messageList: null,
postMessageForm: null,
init: function (view, model) {
this.view = view
this.model = model
this.messageList = this.view.querySelector('.messageList')
this.postMessageForm = this.view.querySelector('.postMessageForm')
this.model.init()
this.loadMessage()
this.bindEvents()
},
loadMessage: function () {
this.model.fetch().then((message) => {
let array = message.map((item) => item.attributes)
array.forEach((item) => {
let li = document.createElement('li')
li.innerText = `${item.name}:${item.content}`
this.messageList.append(li)
})
})
},
bindEvents: function () {
this.postMessageForm.addEventListener('submit', (eee) => {
eee.preventDefault() // 阻止表单提交默认刷新页面事件
this.saveMessage()
})
},
saveMessage: function () {
var name = this.postMessageForm.querySelector('input[name=name]').value
var content = this.postMessageForm.querySelector('input[name=content]').value
// leancloud 提供的保存对象的代码
this.model.save(name, content).then((object) => {
let li = document.createElement('li')
li.innerText = `${object.attributes.name}:${object.attributes.content}`
this.messageList.append(li)
this.postMessageForm.querySelector('input[name=content]').value = ''
})
},
}
// 私有部分是messageList、postMessageForm、loadMessage、bindEvents、saveMessage
// 公有部分是view、model、init的一部分
// 2.类化
window.Controller = function (options) {
// 拿到私有的init
var init = options.init
let object = {
view: null,
model: null,
init: function (view, model) {
this.view = view
this.model = model
this.model.init()
// 调用私有的init
init.call(this, view, model)
// 相当于 options.init.call(object, view, model)
this.bindEvents()
},
}
// 拿到init以外的私有属性
for (let key in options) {
if (key !== 'init') {
object[key] = options[key]
}
}
return object
}
// 3.使用方
var controller = Controller({
init: function (view, model) {
this.messageList = this.view.querySelector('.messageList')
this.postMessageForm = this.view.querySelector('.postMessageForm')
this.loadMessage()
},
loadMessage: function () {
this.model.fetch().then((message) => {
let array = message.map((item) => item.attributes)
array.forEach((item) => {
let li = document.createElement('li')
li.innerText = `${item.name}:${item.content}`
this.messageList.append(li)
})
})
},
bindEvents: function () {
this.postMessageForm.addEventListener('submit', (eee) => {
eee.preventDefault() // 阻止表单提交默认刷新页面事件
this.saveMessage()
})
},
saveMessage: function () {
var name = this.postMessageForm.querySelector('input[name=name]').value
var content = this.postMessageForm.querySelector('input[name=content]').value
// leancloud 提供的保存对象的代码
this.model.save({
'name': name,
'content': content
}).then((object) => {
let li = document.createElement('li')
li.innerText = `${object.attributes.name}:${object.attributes.content}`
this.messageList.append(li)
this.postMessageForm.querySelector('input[name=content]').value = ''
})
},
})
controller.init(view, model)