[JavaScript]MVC浅析

Posted 小粒旬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[JavaScript]MVC浅析相关的知识,希望对你有一定的参考价值。

MVC浅析

MVC或多或少都有听说过,我知道如果要作为一个前端的话,MVC应该是一个显示技术水平的槛,是绕不过去的,所以我乖乖来写这篇文章,对MVC进行一些粗浅的分析和归纳,以加深对MVC的理解。

MVC是一种代码组织形式,他把代码依据功能的不同划分成三个部分,分别是Model、Controller、View。

View代表视图,Model代表对数据的操作(存储和获取等),Controller代表了View和Model两者之间的交互逻辑以及其他。

他们之间的相互作用是这样的:用户对View视图做出了操作,监听着View视图的controller接收到了View的变化通知,然后按需求去调用Model,Model向server发出请求;server返回响应给Model,Model返回数据给Controller,Controller根据接收到的数据更新View视图。

用一张图来表示就是:

技术分享图片

接下来改写一下之前使用leanCloud添加数据库创建留言功能的代码:

//message.js

!function(){
    // 初始化
    var APP_ID = ‘xxxxxxxxxxxxxxxxxxxxxxxxxx‘;
    var APP_KEY = ‘xxxxxxxxxxxxxxxxxxxxxx‘;

    AV.init({
    appId: APP_ID,
    appKey: APP_KEY
    });

    // 拉取历史留言
    var query = new AV.Query(‘Message‘);
    query.find().then(function (messages) {
        messages.forEach(function (item) {
            let li = $(‘<li></li>‘).text(item.attributes.name +‘:‘+item.attributes.content)
            $(‘#comments‘).append(li)
        });
    }).then(function (messages) {
        // 更新成功
    }, function (error) {
        // 异常处理
    });

    let myForm = document.querySelector(‘#postMessage‘)
    // 为什么要监听表单的submit事件而不是button的click事件,因为一旦用户输完密码按回车键提交的话,监听就落空了.submit事件包括了点击和回车
    myForm.addEventListener(‘submit‘,function(e){
        // 阻止传播,防止点击刷新
        e.preventDefault()

        //获取输入框内的值
        let content = $(‘input[name="content"]‘).val()
        let name = $(‘input[name="name"]‘).val()
        var Message = AV.Object.extend(‘Message‘);
        var messages = new Message();
        messages.save({
            "name":name,
            "content":content ,
        }).then(function(object) {
            let li = $(‘<li></li>‘).text(object.attributes.name +‘:‘+ object.attributes.content)
            $(‘#comments‘).append(li)
            myForm.querySelector(‘input[name="content"]‘).value = ‘‘
        })
    })
}.call()

View

View代表视图,因为我们只对这个提交表单和展示列表进行操作,所以View就是:

var view = $(‘section.messages‘)

Model

Model代表对数据的操作(存储和获取等)。

所以Model应该只负责保存提交上来的留言到leanCloud,和从leanCloud获取留言以及数据库初始化的工作(给服务器发送请求,接收服务器响应),返回数据给Controller:

var model = {
    // 初始化
    init : function(){
        var APP_ID = ‘xxxxxxxxxxxxxxxxx‘
        var APP_KEY = ‘xxxxxxxxxxxxxxxxxxxxxxxx‘
        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 messages = new Message();
        return messages.save({
            "name":name,
            "content":content ,
        })
    },
}

Controller

Controller代表了View和Model两者之间的交互逻辑以及其他。

所以,他会负责监听View的事件通知,对Model的调用;从Model获取返回数据,更新View视图。

var controller = {
    view : null,
    model: null,
    init : function(view,model){
        this.model = model
        this.view = view
        this.myForm = document.querySelector(‘#postMessage‘)
        this.model.init()
        this.loadMessages()
        this.bindEvents()
    },

    //加载留言数据
    loadMessages : function () {
        this.model.fetch().then((messages) => {
            messages.forEach((item) => {
                let span = $(‘<span></span>‘).text(‘发布于:‘+ this.parseTime(item.createdAt))[0]
                let li = $(‘<li></li>‘).text(item.attributes.name + ‘:‘ + item.attributes.content)
                li.append(span)
                $(‘#comments‘).append(li)
            });
        }).then(function (messages) {
            // 更新成功
        }, function (error) {
            // 异常处理
        });
    },
    bindEvents : function(){
        this.myForm.addEventListener(‘submit‘,(e) => {
            // 阻止传播,防止点击刷新
            e.preventDefault()

            this.saveMessages()
        })
    },
    saveMessages : function(){
        //保存数据

        //获取输入框内的值
        let content = $(‘input[name="content"]‘).val()
        let name = $(‘input[name="name"]‘).val()
        this.model.save(name,content).then((object) => {
            let span = $(‘<span></span>‘).text(‘发布于:‘+ this.parseTime(object.createdAt))[0]
            let li = $(‘<li></li>‘).text(object.attributes.name +‘:‘+ object.attributes.content)
            li.append(span)
            $(‘#comments‘).append(li)
            document.querySelector(‘#postMessage input[name="content‘).value = ‘‘
        },function(error){
            console.log(error)
        })
    },
    parseTime:function(d){
        const newDate = d.getFullYear() + ‘-‘ + (d.getMonth() + 1) + ‘-‘ + d.getDate() + ‘ ‘
                        + d.getHours() + ‘:‘ + d.getMinutes() + ‘:‘ + d.getSeconds();
        return newDate;
    }
}
controller.init(view,model)

整体MVC

!function(){
    var view = $(‘section.messages‘)

    var model = {
        init : function(){
            var APP_ID = ‘xxxxxxxxxxxxxxxxxxxxxxx‘
            var APP_KEY = ‘xxxxxxxxxxxxxxxxxxxxxxxxxx‘
            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 messages = new Message();
            return messages.save({
                "name":name,
                "content":content ,
            })
        },
    }

    var controller = {
        view : null,
        model: null,
        init : function(view,model){
            this.model = model
            this.view = view
            this.myForm = document.querySelector(‘#postMessage‘)
            this.model.init()
            this.loadMessages()
            this.bindEvents()
        },
        loadMessages : function () {
            this.model.fetch().then((messages) => {
                messages.forEach((item) => {
                    let span = $(‘<span></span>‘).text(‘发布于:‘+ this.parseTime(item.createdAt))[0]
                    let li = $(‘<li></li>‘).text(item.attributes.name + ‘:‘ + item.attributes.content)
                    li.append(span)
                    $(‘#comments‘).append(li)
                });
            }).then(function (messages) {
                // 更新成功
            }, function (error) {
                // 异常处理
            });
        },
        bindEvents : function(){
            this.myForm.addEventListener(‘submit‘,(e) => {
                // 阻止传播,防止点击刷新
                e.preventDefault()

                this.saveMessages()
            })
        },
        saveMessages : function(){
            //获取输入框内的值
            let content = $(‘input[name="content"]‘).val()
            let name = $(‘input[name="name"]‘).val()
            this.model.save(name,content).then((object) => {
                let span = $(‘<span></span>‘).text(‘发布于:‘+ this.parseTime(object.createdAt))[0]
                let li = $(‘<li></li>‘).text(object.attributes.name +‘:‘+ object.attributes.content)
                li.append(span)
                $(‘#comments‘).append(li)
                document.querySelector(‘#postMessage input[name="content‘).value = ‘‘
            },function(error){
                console.log(error)
            })
        },
        parseTime:function(d){
            const newDate = d.getFullYear() + ‘-‘ + (d.getMonth() + 1) + ‘-‘ + d.getDate() + ‘ ‘
                            + d.getHours() + ‘:‘ + d.getMinutes() + ‘:‘ + d.getSeconds();
            return newDate;
        }
    }
    controller.init(view,model)
}.call()

MVC只能使用Controller通过Model操作自身的View,功能划分合理,所以对其他的文件和View来说是解耦的。利于维护和编写。


注意事项

Controller中this的使用,箭头函数不会改变this的指向。

以上是关于[JavaScript]MVC浅析的主要内容,如果未能解决你的问题,请参考以下文章

原创浅析MVC与三层架构

浅析前端开发中的 MVC/MVP/MVVM 模式

PHP代码审计实战思路浅析

ASP.net MVC 代码片段问题中的 Jqgrid 实现

浅析 MVC Pattern

浅析MVC模式与三层架构的区别