mvc与learncloud的实战功能

什么是MVC?

在我的理解里,mvc是一种编写代码的方式。符合了代码分块的思想。使用mvc+面向对象的思想,可以简化代码,分块处理代码。

Model 操作数据
View 表示视图
Controller 是控制器

Model 和服务器交互,Model 将得到的数据交给 Controller,Controller 把数据填入 View,并监听 View
用户操作 View,如点击按钮,Controller 就会接受到点击事件,Controller 这时会去调用 Model,Model 会与服务器交互,得到数据后返回给 Controller,Controller 得到数据就去更新 View。
具体操作如下图
![(2Z5QP2KSICKEBZ_LAROMU.png

下面演示以面向对象的思想进行的MVC操作

1.MVC的View操作

view主要是用来操作用户看的到的视图的,所以View的主要工作就是,获取选择器,由于每一个js文件肯定都要操作这个View,那么可以把View封装成一个类,代码如下

window.View = function(selector){
    return document.querySelector(selector)
        //因为view大家都要调用的所以要把它设置成一个全局对象
}


调用方法:var view = Window.View('#selector') //window 是全局变量可以省略
                  var view = View('#selector') 

2.MVC的Model操作

Model主要是对使用到的数据进行处理,主要有3种方法,init,fetch ,save 方法

具体使用方法如下
var model = {
        initAV: function () {},
        fetch:function(){},
        save:function(){}
    }

把它封装成一个对象
window.Model = function(options){
    let resourceName = options.resourceName
    //注意这个是返回值
    return{
        initAV:function(){
            var APP_ID = 'YHRYNXumFCQUTukhjJ7U8cRL-gzGzoHsz';
            var APP_KEY = 'LAtLqqlwFjlBnnsRGnEEGtQa';

            AV.init({ appId: APP_ID, appKey: APP_KEY });
        },
        fetch:function(){
             这里作为一个类,Message是传入的变量,要在函数开始时确定,这里就 使用到了闭包的知识,Message是这个函数之外的变量
            // var query = new AV.Query('Messsage');
            var query = new AV.Query(resourceName);
            return query.find()
        },
        save:function(object){
            //以封住前的方法为例子,这个方法要传入两个变量,name和content
            //把他封装成一个对象object{'name':name,'content':content}
            var Messsage = AV.Object.extend(resourceName);
            var messsage = new Messsage();
            return messsage.save(object)
        }
    // save:function(name,content){
 //            var Messsage = AV.Object.extend('Messsage');
 //            var messsage = new Messsage();
 //            return messsage.save({
 //                'name': name,
 //                'content': content
 //            })
 //        }
    }
}


使用方法:
var model = Model({resourceName:'Messsage'})
调用这个类的时候就会调用它的三个方法
model.init()
model.fetch()
model.save({'name':name,'content':content})

3.MVC的Controller操作

Controller主要是对使用到的数据进行处理,主要有2种方法,init,bindEvents 方法,有几个重要的属性,view和model,用对象的方式封装代码

第一步:我们先要写一个模板,把大家都会有的属性放在这个模板里
window.controller = function(){
    return{
        view:null,
        model:null,
        init:function(view,model){
            this.view = view
            this.model = model
            this.model.init()
            this.bindEvents()
        },
        bindEvents:function(){}
    }
}

第二步:我们要进行特化,因为我们的要操作的对象的init方法不止有这几个属性,
例如:每个controller特有的方法,我们要做的是就是如果我们初始化这个Controller类的时候(调用Controller类的init方法的时候)
也要调用我们自己写的方法,所以我们要把两个init结合起来

1.我们首先要获取到实例对象的init方法
window.controller = function(option){
    let init =option.init
2.调用完模板的init之后,要调用option的init方法。

//这一步的目的是,调用完模板的init之后
 //要调用option的init方法。
       init.call(this,view,model)
3.注意,这里写错了,这时的this,是函数内的this,所以这个this指的是window。我们要的这个this是option。
所以要把init改成对象。下面还是在修改问题
window.controller = function(option){
    let init =option.init
    //这里的this不在函数里,所以1这个this其实是window
    //我以前以为是window.controller,但是他妈的Controller是我写的一个函数啊
    //执行这个函数的还是window啊,所以下面的代码错了啊
    //this.bindEvents = option.bindEvents()
    
    let object ={
        view:null,
        model:null,
        init:function(view,model){
            this.view = view
            this.model = model
            this.model.init()
            //上面那个改成这样不就没问题了吗
            option.init.bindEvents()
            //这一步的目的是,调用完模板的init之后
            //要调用option的init方法。
            init.call(this,view,model)
        }
    }
    return object
}

在自己的类中的代码:
var controller = Controller({
       init: function (view,model) {
            this.messageList = document.querySelector('#messageList')
            this.form = document.querySelector('#postMessageForm')
            this.loadMessages()

      这个地方因为,模板类中已经对view,model和model.init,也调用了options.bindEvents事件,进行过初始化了,所以不用在自身的init中调用了
        },
这里是我们独有的代码
        loadMessages:function(){
            this.model.fetch().then( (messsage) =>{
                let array = messsage.map(item => item.attributes)
                //map函数的使用map(item => item的操作)
                array.forEach(element => {
                    let li = document.createElement('li')
                    li.innerText = `${element.name}:${element.content}`
                    this.messageList.appendChild(li)
                })

            }, function (error) {

            })
                .then(() => { }, (error) => {
                    console.log(error)
                })
        },

        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':name,'content':content}).then(function (object) {
                alert('留言成功')
                let li = document.createElement('li')
                li.innerText = `${object.attributes.name}:${object.attributes.content}`
                this.messageList.appendChild(li)
            
                myform.querySelector('input[name=name]').value = ' '
                
                myform.querySelector('input[name=content]').value = ' '
            })
        }
    })
}

4. 这里还存在一个问题,就是我们执行这个函数的时候。自己写的函数执行不到啊比如loadMessage等,所以这里要遍历这个option把不是init的属性放到模板里面去
for(let key in option){
            if (key!=='init') {
                object[key] = option[key]
                        //这里要注意我们要把什么赋值,就把他    放前面
//放后面会有他妈的问题!!!!!!!!!
            }
        }

推荐阅读更多精彩内容