首页 > 代码库 > Knockout : 实现复杂的web聊天窗体

Knockout : 实现复杂的web聊天窗体

    公司以前一个同事写的这个聊天的窗体,由于是采用了html拼接的方式,外加处理的时候没有合理的划分职责,导致页面js代码量非常庞大(1500行左右)。现在这哥们离职了,苦的是我们剩下的人,不多说,我先去擦把泪。

  

    公司基本没周都要求给web聊天加各种各样的功能,然后各种不能忍,权衡之后只能选择重构代码,可怜的娃娃啊。。。。

  

    本次完全采用Knockout重构,基础的东西就不多说了,学习Knockout请移步大叔的blog(多谢大叔无私分享)    http://www.cnblogs.com/TomXu/archive/2011/11/21/2257154.html

  

 

  上web聊天界面截图:

  view代码:

<!doctype html><html><head>    <meta charset="utf-8">    <title>后台聊天</title>    <link rel="stylesheet" href="css/jquery.qqFace-min.css" />    <link rel="stylesheet" href="css/index0923.css" />    <style type="text/css">        /*  style="display:none;"  */    </style></head><body>    <div class="chatDiv" id="chatDiv" style="border:1px solid #ededed;">        <!-- 单聊 -->        <div id="singleChat">            <!-- 聊天联系人列表 -->            <div class="chatLp">                <!--div class="title"><a href="http://www.mamicode.com/###" class="clearAll">清空</a></div-->                <div class="title">                    <a href="###" class="sendAll l">群发</a>                    <a href="javascript:void(0);" class="delete r" data-bind="click:function(){viewModel.clearArray();}"></a>                </div>                <ul class="chatList" data-bind="template:{ name: ‘demo‘,foreach:viewModel.viewModelArray}">                    <!--<li><i class="ico icoOne"></i><i class="come"></i><span class="txt">八卦台湾</span></li>                    <li class="select"><i class="ico icoOne"></i><span class="txt">八卦台湾</span></li>                    <li><img class="ico" src="http://www.mamicode.com/images/img.png"/><span class="txt">八卦台湾</span></li>-->                </ul>            </div>            <div class="chatRp">                <div class="chatName" data-bind="template:{ name: ‘title‘,foreach:viewModel.selectViewModel}">                </div>                <!-- 对话内容 -->                <div class="content">                    <div id="chatMain" class="chatMain" style="overflow-y: scroll;" tabindex="5001" data-bind="template:{ name: ‘content‘,foreach:viewModel.selectModel}">                    </div>                    <div class="speakInp">                        <span class="spaeakBtn biaoq"></span>                        <span class="spaeakBtn edit"></span>                        <textarea class="textarea-txt" style="overflow: hidden;" data-bind="value:textContent"></textarea>                        <a class="sub_btn" href="javascript:void(0);" data-bind="click:function(){viewModel.msgPush();}">发送</a>                    </div>                </div>            </div>            <div class="clearB"></div>        </div>    </div>    <div>        <button data-bind="click:add">Add</button>    </div>    <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>    <script type="text/javascript" src="js/jquery.qqFace-min.js"></script>    <script type="text/javascript" src="js/jquery.nicescroll.min.js"></script>    <script src="js/jquery.tmpl.js"></script>    <script src="js/knockout-2.0.0.debug.js"></script>    <script type="text/x-jquery-tmpl" id="demo">        <li data-bind="click:function() {viewModel.select($data)},css:{select:$data.data()==viewModel.selectModel()},    event: { mouseover:function(){ viewModel.showCloseIco($data,true);}, mouseout: function(){ viewModel.showCloseIco($data,false);} }">            <img class="ico" data-bind="css:{icoOne:$data.data().length>0}" src="${ico}"></img>            <span class="txt">${name}</span>            <i class="icodelete" data-bind="click:function () {viewModel.remove($data)},style:{display:$data.isShow()== true?‘inline‘:‘none‘}"></i>        </li>    </script>    <script type="text/x-jquery-tmpl" id="content">        <div class="anotherIetm" data-bind="css:{selfIetm:$data.msgtype  }">            <div class="icoP"><img src="${ico}" class="ico"></div>            <div class="contentP">                <span class="name">${name}</span>                <div class="speakCon">                    <span class="jiao"></span>                    <div class="mainCont">${msg}</div>                    <div class="clearB"></div>                </div>            </div>            <div class="clearB"></div>        </div>    </script>    <script type="text/x-jquery-tmpl" id="title">        <span class="left">${name}</span>        <span class="right">            <span>您的身份:[${serverId}]</span>        </span>        <div class="clearB"></div>    </script>    <script src="ChatModel.js"></script>    <script src="ChatViewModel.js"></script></body></html>

Model代码:

/// <reference path="js/knockout-2.0.0.debug.js" />function LeftObject(ico, name, serverid) {    this.ico = ico;    this.name = name;    this.isShow = ko.observable();    this.data =http://www.mamicode.com/ ko.observableArray();    this.serverId = serverid;}function MsgContent(msgtype, msg, name, ico) {    this.msgtype = msgtype;    this.msg = msg;    this.name = name;    this.ico = ico;}

ViewModel代码:

/// <reference path="js/knockout-2.0.0.debug.js" />//======================左边用户列表操作===========================var num = 0;var viewModel = {    add: function () {        num = num + 1;        viewModel.viewModelArray.push(new LeftObject("http://www.baidu.com/img/bdlogo.png", "Test" + num,"客服-应用主"));        if (viewModel.selectModel().length == 0) {            viewModel.selectModel(viewModel.viewModelArray()[viewModel.viewModelArray().length - 1].data());            viewModel.selectViewModel(viewModel.viewModelArray()[viewModel.viewModelArray().length - 1]);        }    },    push: function () {        if (viewModel.selectModel()) {            viewModel.selectModel.push({ content: num, isSend: (num % 2 == 1) })        }    },    viewModelArray: ko.observableArray()};viewModel.remove = function (e) {    viewModel.viewModelArray.remove(e);    if (viewModel.selectModel() == e.data()) {        viewModel.selectModel([]);    }    viewModel.selectModel(viewModel.viewModelArray()[0].data());    viewModel.selectViewModel(viewModel.viewModelArray()[0]);}viewModel.select = function (e) {    viewModel.selectModel(e.data());    viewModel.selectViewModel(e);}viewModel.selectModel = ko.observableArray();viewModel.selectViewModel = ko.observable();viewModel.showCloseIco = function (e,isShow) {    e.isShow(isShow);    //alert(e.isShow());}viewModel.clearArray = function () {    viewModel.viewModelArray([]);}//===========================分割线 下面是聊天窗口操作函数===========================================viewModel.msgAccept = function (data) {    viewModel.selectModel.push(new MsgContent(true, data, "自己", "images/ico.png"));}viewModel.msgSend = function (data) {    viewModel.selectModel.push(new MsgContent(false, data, "别人", "images/img.png"));}viewModel.textContent = ko.observable();//模拟发送viewModel.msgPush = function (data) {    if (viewModel.viewModelArray().length == 0) {        return;    }    var d = parseInt( Math.random()*10 % 2);    data = viewModel.textContent();    viewModel.textContent(‘‘);    if (d == 0) {        viewModel.msgSend(data);    } else {        viewModel.msgAccept(data);    }}//=====================================================================ko.applyBindings(viewModel);

 

Knockout : 实现复杂的web聊天窗体