看完这篇文章,你将了解

  • 前端代码模块化套路
  • 前端代码 MVC 化套路
  • 其他知识

注:两者都是组织代码的套路,可以先模块化,然后在每个模块内使用 MVC


模块化

当 js 文件里代码太多分不清功能时,模块化可以降低复杂度,提高可读性。

  1. 模块化就是文件分离

将整篇代码分离成一个个文件,并用文件名告诉我们这一段干嘛,那一段干嘛

  1. 相关问题与解决

q:在一个模块声明的变量会成为全局变量,可能与另一个具有同名变量的模块干扰怎么办 ?

a:使用立即执行函数

!function() {
   /* code here */ 
}()

ES 5 里,只有函数有局部变量,只需将整个文件的代码粘贴到立即执行函数内部,就可以把变量转化为局部变量

q2: 既想模块化,又想让模块之间的变量沟通怎么做

a:用 window 声明并使用该变量(化局部变量为全局变量)

module-1.js

!function() {
   var person = window.person = {
       name: 'chan'
   } 
}()

module-2.js

!function() {
    console.log(window.person)
}

或者用 window 声明并使用函数访问该变量(全局函数访问局部变量)

module-1.js

!function() {
    var person = {
        name: 'chan',
        age: 18
    }
    window.growUp = function() {
        person.age += 1
        return person.age
    }
}

module-2.js

!function() {
    var newAge = window.growUp()
    console.log(newAge)
}

MVC 套路

  1. MVC 是什么?

MVC 是写代码的一个套路,可以让代码简明易懂。就前端而言

M 是 model (模型)

model 专注于服务器的交互,与数据打交道。
它的主要职责是将数据上传到服务器、保存到数据库;或从服务器、从数据库将数据取出。

V 是 view (视图)

view 是一个变量,它指向我们操作对象的视图标签

C 是 controller (控制)

controller 专注于与 model、与 view 打交道
一方面,它监听用户对 view 的动作 (bindEvents);指示 view 作出对应更新
另一方面,它从 model 那里取数据;或将得到的数据提交给 model

  1. 形式
// view
var view = document.querySelector(选择器)

// model
var model = {
    init: function() {},
    fetch: function() {}, // 取数据
    save: function() {}   // 存数据
}

// controller
var controller = {
    view: null,
    model: null,
    init: function(view, model) {
      this.view = view
      this.model = model
      this.model.init()
      this.bindEvents()
    },
    bindEvents: function() {}
}

// boot mvc
controller.init(view, model)
  1. 范例
// demo1. 粘性导航栏模块 (只有 VC)
! function() {
    var view = document.querySelector('#NavBar')
    var controller = {
        view: null,
        init: function(view) {
            this.view = view
            this.bindEvents()
        },
        bindEvents: function() {
            var view = this.view
            window.addEventListener('scroll', e => {
                window.scrollY > 0 ? this.active() : this.deactive()
            })
        },
        active: function() {
            this.view.classList.add('sticky')
        },
        deactive: function() {
            this.view.classList.remove('sticky')
        }
    }
    controller.init(view)
}.call()
// demo2. 留言板模块
! function() {
    var view = document.querySelector('.message')

    var model = {
        init: function() {
            let APP_ID = '??'
            let APP_KEY = '??'
            AV.init({ appId: APP_ID, appKey: APP_KEY })
        },
        //获取数据
        fetch: function() {
            var query = new AV.Query('message')
            return query.find() // Promise对象
        },
        //新建数据
        save: function(user, content) {
            var Message = AV.Object.extend('message')
            var message = new Message()
            return message.save({ // Promise对象
                name: user,
                words: content
            })
        }
    }

    var controller = {
        view: null,
        model: null,
        messageList: null,  // 常用 tag:展示版块
        myForm: null,       // 常用 tag:提交版块
        init: function(view, model) {
            this.view = view
            this.model = model
            this.messageList = view.querySelector('#messageList')
            this.myForm = view.querySelector('form')
            
            this.model.init()
            this.loadMessages()
            this.bindEvents()
        },
        bindEvents: function() {
            this.myForm.addEventListener('submit', (e) => {
                e.preventDefault()
                this.saveMessage()
            })
        },
        loadMessages: function() {
            this.model.fetch().then(
                (messages) => {
                    let array = messages.map(value => value.attributes)
                    array.forEach((value) => {

                        this.appendMessage(value.name, value.words)

                        let li = document.createElement('li')
                        li.innerText = `${value.name} says: ${value.words}`
                        document.querySelector('#messageList').appendChild(li)

                    })
                })
        },
        saveMessage: function() {
            let myForm = this.myForm
            let user = myForm.querySelector('input[name=user]').value
            let content = myForm.querySelector('input[name=content]').value
            let isUserEmpty = (user === '') || (user === null) || (user === undefined)
            let isContentEmpty = (content === '') || (content === null) || (content === undefined)
            let isOk = !(isUserEmpty || isContentEmpty)
            if (!isOk) {
                alert('用户名或评论不能为空!')
                return
            }
            this.model.save(user, content).then((object) => {
                this.appendMessage(user, content)
            })
        },
        appendMessage: function(user, content) {
            let li = document.createElement('li')
            li.innerText = `${user} says: ${content}`
            document.querySelector('#messageList').appendChild(li)
        }
    }

    controller.init(view, model)

}.call()

其他知识

引入第三方组件的方法

搜索官网 → get Started → 引入库 → 粘贴代码 → 看注释改代码 → 用单词查文档

用别人东西的套路(CRM )

学习一个框架或组件,可以把示例代码拷贝过来,自己运行运行,然后修改尝试效果,在这个过程掌握相关 api