基于Dojo实现MVC模式下的Ajax应用

本人要实现项目中的一项应用是控制服务端返回来的音频、文字在客户端播放时的同步,相信都看到过baidu的歌曲试听吧,声文同步且支持拖放同步,此次实现多它一个功能,那就是点哪一句就播哪一句(当然我不是为了播放歌曲).简要说我在和服务器的交互中使用JSON(javascript object notation)传输数据,服务端用Newtonsoft的.Net组件处理JSON数据序列化,至于具体的JSON格式那就你自己定义了,例如(最简单的):

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册雅安服务器托管、营销软件、网站建设、柳河网站维护、网站推广。

{ 
      Media : [{
      text : "......",
      start : "...",
            end : "...."
         },  ....]
         }

至于js下的MVC实现,或许许多人这样认为“js仅仅是个脚本而已”,大概应是Ajax的出现改观了许多人对js的看法,其实用js可以写出完全面向对象的程序,因为js支持面向对象语言的几大重要特性,应是一直以来大家所见到的js脚本给大家造成了不好的印象,js原本就是面向对象的语言(我们见到许多由它写成的结构化的程序).看一下这篇文章,我的实现也是受它启发,延伸一点的就是引用Dojo的事件订阅、发布机制.

说一下上述陈述功能的具体的实现,在model方面实现首先实现一个容器型的model,解析JSON数据并拥有当前句信息、所有句信息(数组)、设定当前句方法:

ContainerModel:

dojo.lang.declare('ContainerModel',null,{
    initializer : function(jsonData)
    {
        var jsonObj=dojo.json.evalJson(jsonData);
        var sentences=new Array();
        for(var key in jsonObj.Sentences)
        {
            var sentenceObj=new SentenceModel(key,jsonObj.Sentences[key]);
            sentences.push(sentenceObj);
        }
        this._sentences=sentences;
        this._url=jsonObj.MediaUrl;
        this._selectedSentence = sentences[0]
    },
    
    getSentences : function () {
        return [].concat(this._sentences);
    },

    addItem : function (sentence) {
        this._sentences.push(sentence);
    },    

    setSelected : function (sentence) {
        this._selectedSentence = sentence;
    },
    
    reset : function (){
        this._selectedSentence = this._sentences[0];
    }
});

ItemModel:

dojo.lang.declare('ItemModel',null,{

    initializer : function(id,sentence)

    {

        this._id=id;

        this._jsonSentence=sentence;

       

        dojo.event.topic.subscribe("/PositionChange", this, this.invokeActive);

    },

   

    invokeActive : function(currentPos){

        //if curPos between this.startTime and this.endTime pulish:

        if(this._jsonSentence.StartTime<=currentPos && this._jsonSentence.EndTime>currentPos)

            dojo.event.topic.publish("/MeInvoked", this);

    },

   

    clickActive : function(){

        dojo.event.topic.publish("/MeClicked",this);

    }

});

另一个model代表上述的一句的信息,包含text、startTime、endTime,并且订阅“/positionChange”事件(后面据mediaplayer定时发布),同时定义两方法(此处会于View中用dojo.event的connect将其连于特定的用户事件)用于发布当前对象被激活的事件,于view中同时会为controller订阅此对象激活所发布的事件,controller处理时会刷新container model的当前项同时更新view的表现(如添加样式),其中view对象除了为其他对象进行一些事件连接、订阅外,其render方法负责将container model的所有项render成特定的html元素(如span),其中决定model的显示形式:

Viewer - Controller:

/**
 * a container view class to render on the webpage
 */
dojo.lang.declare('MainView',null,{
    initializer : function(model,controller,elements){
        this._model=model;
        this._controller=controller;
        this._elements=elements;
       
        dojo.event.topic.subscribe("/MeInvoked", this._controller, this._controller.proccessInvoke);
        dojo.event.topic.subscribe("/MeClicked", this._controller, this._controller.proccessClick);
    },
   
    render : function(){
        var div = this._elements.div;
        //remove children
        for(var i=0;i        {
            div.removeChild(div.childNodes[i]);
        }
        div.innerHTML="";
        div.innerText="";
       
        var items = this._model.getSentences();
        for (var key in items) {
            var span = document.createElement("span");
            span.id=items[key]._id;
            span.appendChild(document.createTextNode(items[key]._jsonSentence.Sentence));
            span.appendChild(document.createElement("br"));
            div.appendChild(span);
           
            if(key==0)
                dojo.html.addClass(document.getElementById(this._model._selectedSentence._id),"selected");
           
            dojo.event.connect(span, 'onclick', items[key], 'clickActive');
        }
    }
   
});

/**
 * a common controller class,
 * execute some utilities operations.
 */
dojo.lang.declare('MainController',null,{
    initializer : function(model){
        this._model=model;
    },
   
    displaySentence : function(){       
        //actual method
        dojo.event.topic.publish("/DisplaySentence",this._model._selectedSentence._jsonSentence);
    },
   
    proccessInvoke : function(sentence){
        //proccess details
        this.proccessRightShow(sentence);       
    },
   
    proccessClick : function(sentence){
        //proccess details
        this.proccessRightShow(sentence);       
        //set player pos(start,end)
        setPlayerPos(sentence._jsonSentence.StartTime);
    },
   
    proccessRightShow : function(sentence){
        //lighten sentence and show sentence on the right
       
        if(this._model._sentences[0]==sentence || this._model._selectedSentence!=sentence)
        {
            //change origin selectedSentence's css
            dojo.html.removeClass(document.getElementById(this._model._selectedSentence._id),"selected");
            this._model.setSelected(sentence);
            //change new current selectedSentence's css
            dojo.html.addClass(document.getElementById(this._model._selectedSentence._id),"selected");
            document.getElementById(parseInt(this._model._selectedSentence._id/1.2)).scrollIntoView(true);
            //pass sentence to show in right in another func
            this.displaySentence();
        }
    }
});

大概模式如下:

图中对象初始化会subscribe合适的事件以待事件publish时进行处理,其中虚线表示一次用户点击处理,而自由线表示随播放进行处理文本同步(如加亮当前项)的过程,此过程在播放过程中持续进行。其实,事件发布并非图中所示指向特定对象(图中为了容易理解),是谁订阅谁处理,有AOP的意味!

相信有了这些,让这个模型运行起来是没问题了吧,忙中抽闲和大家分享,另外dojo的require不要忘了

dojo.require('dojo.lang.*');
dojo.require("dojo.event.*");
dojo.require("dojo.event.topic");
dojo.require("dojo.html.*");
dojo.require("dojo.json");
dojo.require("dojo.io.*");

脚本的开发还是比较困难的,从开发环境、或从其控制来讲,正如Pragmatic Programmer中所说的,“不***的系统、荒谬的时间标度、可笑的工具、还有不可能实现的需求--在这样一个世界上,让我们安全‘驾驶’”!

【编辑推荐】

  1. AJAX和XmlHttpRequest下的Web开发
  2. 浅谈Ajax在ASP.Net中的使用
  3. 使用AJAX扩展器自定义控件

网站名称:基于Dojo实现MVC模式下的Ajax应用
文章来源:http://www.shufengxianlan.com/qtweb/news18/274868.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联