JavaScript实现MVC 发表于 2019-02-24 | 分类于 JavaScript VC设计模式封装前看完《javascript设计模式》,将自己之前写的插件,用MV及MVC设计模式重新封装了一遍 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283// sticky-topbar.js!function () { window.addEventListener("scroll", function () { if (window.scrollY > 0) { topNavBar.classList.add('sticky') } else { topNavBar.classList.remove('sticky') } })}.call()// smoothly-navigation.js!function () { let aTags = document.querySelectorAll('nav.menu > ul > li > a') function animate(time) { requestAnimationFrame(animate); TWEEN.update(time); } requestAnimationFrame(animate); for (let i = 0; i < aTags.length; i++) { aTags[i].onclick = function (x) { x.preventDefault() let a = x.currentTarget let href = a.getAttribute('href') //'#siteAbout' let element = document.querySelector(href) let top = element.offsetTop let currentTop = window.scrollY let targetTop = top - 80 let s = targetTop - currentTop // 路程 var coords = { y: currentTop }; // 起始位置 var t = Math.abs((s / 100) * 300) // 时间 if (t > 500) { t = 500 } var tween = new TWEEN.Tween(coords) // 起始位置 .to({ y: targetTop }, t) // 结束位置 和 时间 .easing(TWEEN.Easing.Cubic.InOut) // 缓动类型 .onUpdate(function () { // coords.y 已经变了 window.scrollTo(0, coords.y) // 如何更新界面 }) .start(); // 开始缓动 } }}.call()//message.js!function () { var APP_ID = 'baTF3mT0Ybt7NcGffQphNKDW-gzGzoHsz'; var APP_KEY = '02G0rMK0z1bMwV1mvUhOIRpi'; AV.init({ appId: APP_ID, appKey: APP_KEY }); myForm.addEventListener("submit", function (e) { e.preventDefault() var remark = document.querySelector("input[name='remark']").value var name = document.querySelector("input[name='name']").value var TestObject = AV.Object.extend('message') var testObject = new TestObject() testObject.save({ remark: remark, name: name }).then(function (testObject) { var li = document.createElement("li") li.innerText = `${testObject.attributes.name}:${testObject.attributes.remark}` var ul = document.querySelector("#content") ul.appendChild(li) document.querySelector("input[name='remark']").value = "" document.querySelector("input[name='name']").value = "" }) }) var query = new AV.Query('message'); query.find().then(function (remarks) { var aRemark = remarks.map(function (v) { return v.attributes }) aRemark.forEach(function (v) { var li = document.createElement("li") li.innerText = `${v.name}:${v.remark}` var ul = document.querySelector("#content") ul.appendChild(li) }); });}.call() VC设计模式封装后123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140// sticky-topbar.js!function () { var view = document.querySelector("#topNavBar") var controller = { view: null, init: function (view) { this.view = view this.bindEvents() // this.bindEvents.call(this) }, bindEvents: function(){ window.addEventListener("scroll", function () { if (window.scrollY > 0) { this.active() } else { this.deactive() } }.bind(this)) }, active: function(){ this.view.classList.add('sticky') }, deactive:function(){ this.view.classList.remove('sticky') } } controller.init(view) // controller.init.call(controller,view)}.call()// smoothly-navigation.js!function () { var view = document.querySelector("nav.menu") var controller = { view: null, init: function (view) { this.view = view this.bindEvents() this.initAnimation() }, bindEvents: function () { let aTags = view.querySelectorAll('ul > li > a') for (let i = 0; i < aTags.length; i++) { aTags[i].onclick = function (x) { x.preventDefault() let a = x.currentTarget let href = a.getAttribute('href') //'#siteAbout' let element = document.querySelector(href) this.scrollToElement(element) } } }, initAnimation: function () { function animate(time) { requestAnimationFrame(animate); TWEEN.update(time); } requestAnimationFrame(animate); }, scrollToElement: function (element) { let top = element.offsetTop let currentTop = window.scrollY let targetTop = top - 80 let s = targetTop - currentTop // 路程 var coords = { y: currentTop }; // 起始位置 var t = Math.abs((s / 100) * 300) // 时间 if (t > 500) { t = 500 } var tween = new TWEEN.Tween(coords) // 起始位置 .to({ y: targetTop }, t) // 结束位置 和 时间 .easing(TWEEN.Easing.Cubic.InOut) // 缓动类型 .onUpdate(function () { // coords.y 已经变了 window.scrollTo(0, coords.y) // 如何更新界面 }) .start(); // 开始缓动 } } controller.init(view)}.call()// message.js!function () { var view = document.querySelector("#message") var controller = { view: null, messageList: null, form: null, initAv: function () { var APP_ID = 'baTF3mT0Ybt7NcGffQphNKDW-gzGzoHsz'; var APP_KEY = '02G0rMK0z1bMwV1mvUhOIRpi'; AV.init({ appId: APP_ID, appKey: APP_KEY }); }, init: function (view) { this.view = view this.form = view.querySelector("form") this.messageList = view.querySelector("#content") this.initAv() this.loadMessages() this.bindEvents() }, bindEvents: function () { this.form.addEventListener("submit", (e) =>{ e.preventDefault() console.log(this) this.saveMessage() }) }, saveMessage: function () { var remark = this.form.querySelector("input[name='remark']").value var name = this.form.querySelector("input[name='name']").value var TestObject = AV.Object.extend('message') var testObject = new TestObject() testObject.save({ remark: remark, name: name }).then((testObject) => { var li = document.createElement("li") li.innerText = `${testObject.attributes.name}:${testObject.attributes.remark}` this.messageList.appendChild(li) this.form.querySelector("input[name='remark']").value = "" this.form.querySelector("input[name='name']").value = "" }) }, loadMessages: function () { var query = new AV.Query('message'); query.find().then((remarks) => { var aRemark = remarks.map(function (v) { return v.attributes }) aRemark.forEach((v) => { var li = document.createElement("li") li.innerText = `${v.name}:${v.remark}` this.messageList.appendChild(li) }); }); } } controller.init(view)}.call() MVC设计模式封装例子123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899// index.html<!DOCTYPE html><html lang="zh-Hans"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <!-- 存储服务 --> <script src="//cdn.jsdelivr.net/npm/leancloud-storage@3.15.0/dist/av-min.js"></script> <!-- 即时通讯服务 --> <script src="//cdn.jsdelivr.net/npm/leancloud-realtime@4.3.1/dist/realtime.browser.min.js"></script></head><body> <section id="message"> <ul id="content"></ul> <form id="myForm"> <label>姓名:<input type="text" name="name"></label> <label>留言:<input type="text" name="remark"></label> <input type="submit" value="提交"> </form> </section> <script src="message.js"></script></body></html>// message.js!function(){ var model = { // 获取数据 init: function(){ var APP_ID = 'TsDnap9SEXjSvGSowP7gXXJC-gzGzoHsz' var APP_KEY = 'rGye31p12mM3wFpNRn9RADu9' AV.init({ appId: APP_ID, appKey: APP_KEY }) }, fetch: function(){ var query = new AV.Query('Message'); return query.find() // Promise 对象 }, // 创建数据 save: function(name, content){ var Message = AV.Object.extend('Message'); var message = new Message(); return message.save({ // Promise 对象 'name': name, 'content': content }) } } var view = document.querySelector('section.message') var controller = { view: null, model: null, messageList: null, init: function(view, model){ this.view = view this.model = model this.messageList = view.querySelector('#messageList') this.form = view.querySelector('form') this.model.init() this.loadMessages() this.bindEvents() }, loadMessages: function(){ this.model.fetch().then( (messages) => { let array = messages.map((item)=> item.attributes ) array.forEach((item)=>{ let li = document.createElement('li') li.innerText = `${item.name}: ${item.content}` this.messageList.appendChild(li) }) } ) }, bindEvents: function(){ this.form.addEventListener('submit', (e) => { e.preventDefault() this.saveMessage() }) }, saveMessage: function(){ let myForm = this.form let content = myForm.querySelector('input[name=content]').value let name = myForm.querySelector('input[name=name]').value this.model.save(name, content).then(function(object) { let li = document.createElement('li') li.innerText = `${object.attributes.name}: ${object.attributes.content}` let messageList = document.querySelector('#messageList') messageList.appendChild(li) myForm.querySelector('input[name=content]').value = '' console.log(object) }) } } controller.init(view, model)}.call()