mvc架构和bs架构的区别 mvc与bs_mvc

MVC是一种设计模式,既是一种代码组织形式又是一种思想,他将系统分为三层:Model 数据,View 视图,Controller 控制器。

Model数据管理:专门处理数据,包括数据逻辑,数据请求,数据存储。它不对HTML,DOM,CSS以及视图逻辑进行操作,一般多数用于从服务器获取数据和保存数据。

View视图:即为用户可见区域,前端view主要负责HTML的渲染。

Controller控制器:主要负责view事件的逻辑处理,并更新Model,也监听View,总而言之Controller控制除视图和数据以外所有的事情。

下面我们通过一个原生JS例子来认识MVC这种设计模式。


这是一个留言板功能模块,我从leancloud注册了一个账号,作为数据库。然后在html中加入提交表单,绑定表单事件。输入信息提交后由js向leancloud服务器申请保存数据,保存成功后我们再从leancloud中拿到数据渲染到页面中,就这样简单的一个功能模块,我们试着用MVC的设计模式重构一遍。

重构前:

html

<script src="//cdn.jsdelivr.net/npm/leancloud-storage@3.14.0/dist/av-min.js"></script>
<section class="leave">
    <h2>留言板</h2>
    <ol id="messageList"></ol>
    <div class="inputBox">
        <form id="message">
            <div>
                昵称<input type="text" autocomplete="off" name="name">
            </div>
            <div>
                内容<input type="text" autocomplete="off" name="content">
            </div>
            <input type="submit" name="提交" style="margin-top: 20px">
        </form>
    </div>
</section>

JS

//leancloud初始化,
var APP_ID = '6cdlCTFh4O4BU9GaTp79Fc4R-gLGzoHsz';
var APP_KEY = 'PrnMib9dmf7qc9B4vEEvOfm6';

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

//从leancloud拿到数据
let query = new AV.Query('A_Tione')
query.find().then(e=>{
    let array = e.map(item=> item.attributes)//拿到A_Tione的留言数据
    console.log(array)
    array.forEach((item)=>{
        let li = document.createElement('li')
        li.innerText = item.name+':'+item.content
        messageList.appendChild(li)
    })

})

//将表单数据保存到leancloud中
let myForm = document.querySelector('#message')
myForm.addEventListener('submit', function (e) {
    e.preventDefault() //阻止默认事件
    let name = myForm.querySelector('input[name=name]').value
    let content = myForm.querySelector('input[name=content]').value
    let Tione = AV.Object.extend('A_Tione');
    let tione = new Tione();
    tione.save({
        'name': name,
        'content': content
    }).then(function(object) {
        let li = document.createElement('li')
        li.innerText = name+':'+content
        messageList.appendChild(li)
        myForm.querySelector('input[name=name]').value = ''
        myForm.querySelector('input[name=content]').value = ''
        console.log('保存成功')
    })

})

 我们可以看到代码是一坨坨的,需要用注释来区分 第一段是初始化,第二段是拿数据,第三段是保存数据。

现在代码少加上注释看起来还挺好理解的,可是代码行数上去了,哪怕加注释恐怕理解起来也不太容易,而且加太多注释同样耽误时间。于是乎经过程序员们不断地摸索,最后发现了一个办法,就是用MVC的思想,将代码分类整理,按照功能分为数据管理,视图和逻辑控制。


重构后:

第一步:

我们将html中包裹整个留言模块的DOM对象存入view变量中,这一步就是MVC中的V,view 视图

第二步:

然后在model对象中定义leancloud初始化,获取数据和新增数据,注意model中只做数据相关的逻辑以及拿数据和保存数据,其它的逻辑统统交给controller完成。这步就是MVC中的M,model 数据管理

第三步:

我们在controller对象中先定义好view: null, model: null, messageList: null,然后由controller中的init初始化从controller外面拿view,model,messageList。将他们三个的值保存到controller内部作用域中,这样的好处就是所有要用到的东西我们都能在controller中找到,不必再从外面调取,而且需要传进来的值已经定义好放在那了,你只需要按部就班地将需要的值传给定义好的空属性即可。

然后调用接下来的方法函数,进行视图相关的逻辑操作。例如在获取数据时调用model里面的this.model.fetch()方法,得到一个promise对象然后接zhen()继续后面的逻辑操作。这样数据处理model与视图逻辑处理controller就解耦了,各自处理各自的事儿,不用像原来的代码全部混在一坨,需要看完所有的代码才能理解写的什么。最后这步就是MVC中的C,controller 控制器

理解了这个例子,你就会发现后面写代码都是一个套路,view相关的html,model数据处理,controller定义好需要用到的属性初始化,然后将视图相关的逻辑全部放在controller里面,最后controller.init(view, model)一下将view和model传入controller即可。

好处:

  • 按MVC思想将代码划分好后,就不用费力写注释,因为一眼就知道代码在干嘛。
  • 增强代码阅读性
  • 省事,按照MVC模板一套,改改controller的视图处理逻辑、model的数据请求与相应,一个模块就写完了。
!function () {
    let view = document.querySelector('section.leave')
    let model = {
        init: function () {
            let APP_ID = '6cdlCTFh4O4BU9GaTp79Fc4R-gLGzoHsz';
            let APP_KEY = 'PrnMib9dmf7qc9B4vEEvOfm6';
            AV.init({appId: APP_ID, appKey: APP_KEY});
        },
        fetch: function () {//获取数据
            let query = new AV.Query('A_Tione')
            return query.find() //返回一个Promise对象
        },
        save: function (name, content) {
            let Tione = AV.Object.extend('A_Tione');
            let tione = new Tione();
            if (name && content) {
                return tione.save({//返回一个Promise对象
                    'name': name,
                    'content': content
                })
            }
        }
    }

    let 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(e => {
                let array = e.map(item => item.attributes)//拿到A_Tione的留言数据
                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 name = myForm.querySelector('input[name=name]').value
            let content = myForm.querySelector('input[name=content]').value
            this.model.save(name, content).then(object => {
                let li = document.createElement('li')
                li.innerText = name + ':' + content
                this.messageList.appendChild(li)
                myForm.querySelector('input[name=name]').value = ''
                myForm.querySelector('input[name=content]').value = ''
                console.log('保存成功')
            })
        },
    }
    controller.init(view, model)
}.call()

mvc架构和bs架构的区别 mvc与bs_mvc设计_02