模块化(MVC的M)
-
MVC(Model View Controller)
- 我们在写了一周的代码之后,当过了一周之后,我们忘记了之前怎么想的。MVC就是为了解决这样的问题
-
我们可以使用文件名来告诉自己代码是用来干啥的,不需要使用注释,这就是模块化
- 上面这种写法就是模块化代码。将不同的功能代码放到不同的文件中,并使用简明的名称加以区分以及引用
- 使用MVC的前提是模块化
MVC的V和C
-
我们看一下之前写的init-swiper.js
!function(){ var mySwiper = new Swiper ('.swiper-container', { // Optional parameters // direction: 'vertical', loop: true, // If we need pagination pagination: { el: '.swiper-pagination', }, // Navigation arrows navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, // And if we need scrollbar // scrollbar: { // el: '.swiper-scrollbar', // }, }) }.call()
-
我们看到这个函数其实操作的是属性weightswiper-container的div,这个被掌控的元素就是View,我们可以在外层套一个,将整体作为View,这个外层的div就是init-swiper的View
-
View是用户能看到的东西,我们其实就一直在使用View。我们可以在操作MVC的时候先拿到这个View,这样的一个意义就是页面其实分块化了
-
我们将所有能使用View的代码都改进成使用View,其实每一个View就是代表了页面中那一个模块属于当前操作的对象
!function(){ window.addEventListener('scroll', function(x){ if(window.scrollY > 0){ topNavBar.classList.add('sticky') }else{ topNavBar.classList.remove('sticky') } }) }.call()
改进成
!function(){ var view = document.querySelector('#topNavBar') window.addEventListener('scroll', function(x){ if(window.scrollY > 0){ view.classList.add('sticky') }else{ view.topNavBar.classList.remove('sticky') } }) }.call()
只要我们操作页面,都会有一个可以看到的View在页面中。
-
C就是控制,我们将上面的代码改成如下形式,就是使用C了。我们有一个View的对象,有一个Controller的对象初始化放在Controller中,对View的操作也都放在Controller中
!function(){ var view = document.querySelector('#topNavBar') var controller = { view: null, init: function(view){ var view = this.view window.addEventListener('scroll', function(x){ if(window.scrollY > 0){ view.classList.add('sticky') }else{ view.topNavBar.classList.remove('sticky') } }) } } controller.init(view) }.call()
MVC解决的是之前每一个操作对象,一个方法,现在实现规范化,将它们的结构变的相同,每一个模块都有一个Controller,用Controller操作View
箭头函数内外的this是不变的
-
我们可以对函数更加精进,细化
!function(){ var view = document.querySelector('#topNavBar') var controller = { view: null, init: function(view){ this.view = view this.bindEvents() }, // 绑定函数里面只做绑定的事情,其余操作放到外面,方便管理 bindEvents: function(){ var view = this.view // 这边使用箭头函数是因为箭头函数没有this,其this跟外层一样 window.addEventListener('scroll', (x) => { if(window.scrollY > 0){ this.active() }else{ this.deactive() } }) }, active: function(){ view.classList.add('sticky') }, deactive: function(){ view.topNavBar.classList.remove('sticky') } } controller.init(view) }.call()
-
我们发现我们该有的东西全部在controller上面了
!function(){ // 我们拿到这个view var view = document.querySelector('#mySlides') var controller = { view: null, swiper: null, swiperOptions: { loop: true, pagination: { el: '.swiper-pagination', }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', } }, init: function(){ this.view = view this.initSwiper() }, initSwiper: function(){ this.swiper = new Swiper ( this.view.querySelector('.swiper-container'), this.swiperOptions )} } controller.init(view) }.call()
!function(){ var view = document.querySelector('nav.menu') var controller = { view: null, aTags: null, initAnimation: function(){ function animate(time) { // this.animate里面的this会变化,所以我们需要进行bind,否则会出错 requestAnimationFrame(animate); TWEEN.update(time); } requestAnimationFrame(animate); }, scrollToElement: function(element){ let top = element.offsetTop // let top = document.querySelector(x.currentTarget.getAttribute('href')).offsetTop let currentTop = window.scrollY let targetTop = top - 80 let s = targetTop - currentTop const coords = { y: currentTop} var t = Math.abs((s/100)*150) if(t>500){t = 500} const tween = new TWEEN.Tween(coords) .to({y: targetTop}, t) .easing(TWEEN.Easing.Quadratic.InOut) .onUpdate(() => { window.scrollTo(0, coords.y) }) .start(); }, bindEvents: function(){ this.aTags = this.view.querySelectorAll('nav.menu > ul > li > a') for(let i=0; i<this.aTags.length; i++){ this.aTags[i].onclick = (x) => { x.preventDefault() let a = x.currentTarget let href = a.getAttribute('href') let element = document.querySelector(href) this.scrollToElement(element) } } }, init: function(view){ this.view = view this.initAnimation() this.bindEvents() } } controller.init(view) }.call()