最近在看node.js的web开发框架Clouda,目前的版本为0.9,看来第一个大版本1.0的功能应该基本齐全了。

那么这里就试着开发出一个简单的留言板系统实例,和大家分享一下。


安装配置什么的就不说了,留言板也比较简单,一个输入框,一个留言列表。下面就直接上代码了。

建立一个messageboard的项目。

首先是model,数据模型包括用户名、时间、留言内容。

Model.messageboard = function(exports){
    exports.config = {
        fields: [
            {name:'name', type:'string'},
            {name:'message', type:'string'},
            {name:'time', type:'datetime',defaultValue:'now()'}
        ]
    };
};

然后是controller,包括PubSub模型和场景的生命周期管理。

publish下的:

module.exports = function(fw){
    fw.publish('messageModel', 'pub-messageboard', function(callback){
        var collection = this;
        collection.find({}, {sort:[['time',1]]}, function(err, items){
            callback(items);
         });
    },
    {
        beforeInsert : function(serverCollection, structData, userinfo, callback){
                                                                                            
            structData.time = (new Date()).valueOf();           // 以服务器时间为准        
            callback(structData);        
        }
    });
};

controller下的:

sumeru.router.add(
        {
            pattern: '/messageboard',
            action: 'App.messageboard'
        }
    );
sumeru.router.setDefault('App.messageboard');
App.messageboard = sumeru.controller.create(function(env, session){
                                                                                           
    var getMsgs = function(){
        session.messages = env.subscribe('pub-messageboard', function(msgCollection){
            session.bind('messageboard_container', {
                    data    :   msgCollection.find(),
            });
        });
    };
                                                                                           
    //onready is respond for event binding and data manipulate
    env.onready = function(){
        session.event('messageboard_container', function(){
            document.getElementById("messages").style.height = document.body.clientHeight - 80 + "px";
            document.getElementById('messages').scrollTop = document.getElementById('messages').scrollHeight;
        });
       window.onresize = function(){
            document.getElementById("messages").style.height = document.body.clientHeight - 80 + "px";
            document.getElementById('messages').scrollTop = document.getElementById('messages').scrollHeight;
       };
                                                                                               
        session.eventMap('#inputMessage', {
            'keydown' : function(e){
                if(e.keyCode == 13){
                    sendMessage();
                }
            }
        });
                                                                                                   
        //send message
        document.getElementById("send").addEventListener('click',sendMessage);
    };
                                                                                           
    var sendMessage = function(){
        var input = document.getElementById('inputMessage'),
            inputVal = input.value.trim();
                                                                                                   
        var inputName = document.getElementById('inputName'),
            inputValName = inputName.value.trim();
                                                                                           
        if (inputVal == '' || inputValName == '') {
                                                                                                   
            alert("用户名和消息不能为空!");
            return false;
        };
        session.messages.add({
            name: inputValName,
            message : inputVal,
            time : (new Date()).valueOf()
        });
                                                                                           
        session.messages.save();
        input.value = '';
        input.focus();         
    };
                                                                                           
    //onload is respond for handle all data subscription
    env.onload = function(){         
        return [getMsgs];         
    };
                                                                                           
    //sceneRender is respond for handle view render and transition
    env.onrender = function(doRender){
        doRender('messageboard', ['push', 'left']);
    };
                                                                                           
                                                                                           
});

然后是view,显示一个输入框和所有的留言。

<div style="width:800px;margin:auto;">
                                                 
        <h1>留言板</h1>                      
                                                 
                                                     
    <div>
        <label for="inputName">昵称:</label><input id="inputName" placeholder="Name" /><br />
        <input id="inputMessage" placeholder="请在此处留言!" style="height:80px;width:700px;" /><br />
        <button id="send">提交</button>
    </div>  
    <block tpl-id="messageboard_container">
        <div id="messages" style="border-top:1px solid #333;margin:15px;">
                                                         
            {{#each data}}
                <div class="username" style="border-top:1px dotted #333;margin-top:15px;">`this`.`username`<span class="time" style="padding-left:20px;">{{$Library.getChatTime.getTime(this.time)}}</span></div>
                <div class="content">
                    `this`.`message`
                </div>  
            {{/each}}
                                                         
        </div>
    </block>
                                                 
                                                 
</div>


然后在浏览器中输入:

http://localhost:8080/debug.html/messageboard

出现wKioL1Lh3ezg1pLuAAFIW7FMru8798.jpg

大功告成~