IceMx.Mvc 我的js MVC 框架 三、动手来写一个评论模块儿
介绍
本人菜鸟,一些自己的浅薄见解,望各位大神指正。
本框架有以下优点
1、简单(调用简单、实现简单、不过度设计)
2、视图、控制器、模型分离(分离对于维护十分有必要)
3、组件化(每一个mvc模块儿的实现都是一个组件的实现,M+V+C = 组件)
视图
1 <div id="iceDiscussView"> 2 <!--List 评论主体模板--> 3 <div id="iceDiscussViewBody"> 4 <span class="ll"> 5 <textarea id="@{iceId1}" data-id="iceTxtContent" rows="3" cols="50" invalue="发表点什么吧……" style="color: black;"></textarea></span> <span class="ll"> 6 <input id="iceBtnSub" type="button" value="发送" style="height: 54px;" /></span> 7 <br class="clear"> 8 <span><a href="javascript:void(0)" onclick="FACE.Show('@{iceId1}',this)"><img src="/img/face/bq_btn.png" /></a> <a href="javascript:void(0)" id="iceDiscussShow">展开评论<span id="iceDiscussCount"></span></a> </span> 9 <div id="iceDiscussPanel" > 10 </div> 11 </div> 12 13 <!--List 模板--> 14 <div id="iceDiscussViewList" style='padding:5px 3px 5px 3px; border:1px dotted #cccccc'> 15 <div style="height:40px;"> <strong> @{userName}:发表于@{insTime}</strong> 16 </div> 17 <div>@{content}</div> 18 <div> 19 <a id="iceDiscussReplyLink" href="javascript:void(0)" data-discussId="@{discussId}" >回复<span>@{replyCountStr}</span></a> 20 <br /> 21 </div> 22 <div id="iceDiscussReplyList"> 23 24 </div> 25 </div> 26 27 <div id="iceDiscussViewRepyList" style='padding:5px 3px 5px 25px; border:1px dotted #cccccc'> 28 <div style="height:40px;"> <strong> @{userName}:回复你@{insTime}</strong> 29 </div> 30 <div>@{content}</div> 31 </div> 32 33 </div>
视图就不用说了,其实也可以叫他模板。@{userName}这些标志会替换成相应的数据。
比较特殊的是@{iceId1} 他会替换成一个随机id。
模型
1 function DiscussModel() { 2 this.GetList = function () { 3 var list = [{ discussId:1,userName: "张三", content: "你好,空间不错!", insTime: "2013-08-01", replyCount: 0 } 4 , { discussId: 2, userName: "李四", content: "你好,空间不错!", insTime: "2013-08-01", replyCount: 3 } 5 ] 6 7 $.each(list, function (i,data) { 8 if (data.replyCount == 0) { 9 data.replyCountStr = ""; 10 } else { 11 data.replyCountStr = "("+data.replyCount+")"; 12 } 13 }) 14 15 return list; 16 } 17 this.GetListCount = function () { 18 return 2; 19 } 20 this.Add = function (content, userName) { 21 var data = { content: content, userName: userName, insTime: IceMx.Date.Now()} 22 //这里是aja提交方法 23 return data; 24 } 25 26 this.GetListReply = function (discussId) { 27 if(discussId==2){ 28 return [{ userName: "IceMx", content: "谢谢关注!", insTime: "2013-8-31" } 29 ] 30 } 31 } 32 }
主要负责数据的处理,这里是模拟了数据,实际情况可能会是通过ajax从后台返回,目前只支持ajax的同步模式,异步模式我还没有处理。
控制器
var DiscussController = IceMx.Mvc.NewController("Discuss", function () { //定义局部变量 var model = new DiscussModel(), _self = this, $body = $(IceMx.Model.Format(this.GetView("#iceDiscussViewBody").toString(), {})), $txt = this.GetView("[data-id='iceTxtContent']", $body), $btnSub = this.GetView("#iceBtnSub", $body), $iceDiscussShow = this.GetView("#iceDiscussShow", $body), $iceDiscussCount = this.GetView("#iceDiscussCount", $body), $replyMuBan = this.GetView("#iceDiscussViewRepyList").toString(), discussCount = 0; //定义模板 this.listMuBan = this.GetView("#iceDiscussViewList").toString(); //私有方法 function SetDiscussCount(count) { if (typeof count == "string") { eval("discussCount=discussCount" + count); } else { discussCount = count; } if (discussCount == 0) { return; } $iceDiscussCount.html("(" + discussCount + ")"); } function Init() { IceMx.Common.BindDefaultText($txt).BindEnter($txt, function () { $btnSub.click(); }); $btnSub.click(function () { _self.Add($txt.val(), "王龙").appendTo("#iceDiscussPanel", $body); }); SetDiscussCount(model.GetListCount()); } //共有方法 this.GetListHtml = function () { var list = model.GetList(), htm = ""; $.each(list, function (i,data) { htm += IceMx.Model.Format(_self.listMuBan, data); }) var discussHtm = $(htm); discussHtm.delegate("#iceDiscussReplyLink", "click", function () { var discussId=this.attributes["data-discussId"].value, list = model.GetListReply(discussId), $this= $(this), htm = ""; if(list){ $.each(list, function (i, data) { htm += IceMx.Model.Format($replyMuBan, data); }) _self.GetView("#iceDiscussViewList", $this).find("#iceDiscussReplyList").append(htm); } }) SetDiscussCount(list.length); return discussHtm; } this.GetBody = function () { $body = $(IceMx.Model.Format(this.GetView("#iceDiscussViewBody").toString(), {})), $body.find("#iceDiscussPanel").html("").append(this.GetListHtml()); return $body; } this.Add = function (content, userName) { var data = model.Add(content, userName); var htm = IceMx.Model.Format(_self.listMuBan, data); SetDiscussCount("+1"); $txt.val("").blur(); IceMx.tip("提交成功……"); return $(htm); } Init(); });
控制器主要负责作为数据和视图的桥梁,视图内一些事件也是通过它来注册的。
这里的 this.GetView 是获取视图,之所以可以这样用原因是在组件加载的时候进行了视图绑定到控制器。
调用端
1 <script> 2 var discussController, FACE; 3 4 IceMx.Mvc.Get("Discuss","Face"); 5 6 IceMx.Event.AddEvent("MvcLoadOver", function () { 7 FACE = new FaceController(); 8 discussController = new DiscussController(); 9 discussController.GetBody().appendTo("#panelDiscuss"); 10 }); 11 </script> 12 </head> 13 <body> 14 <form id="form1" runat="server"> 15 <h1>Js Mvc 模式体验</h1> 16 <div style="border:1px solid #cccccc ; padding:5px;"><span><b>基于js的mvc三层架构设计体验</b></span> 17 18 <div style="background-color:#f8f8f8;padding:10px;"> 19 <p>尝试用异步加载的mvc方式来实现一个评论功能。</p> 20 <p>1、Controller 实现和页面的交互 。</p> 21 <p>2、Model 负责和数据层交互。</p> 22 <p>2、View 页面上的html代码模板。</p> 23 <p> 24 异步加载:不需要事先应用mvc的js和其他内容。 25 加载代码:IceMx.Mvc.Get("Discuss","Face"); 26 </p> 27 <p>该代码加载了两个mvc模块,加载后将通知 MvcLoadOver 的注册者,在该事件内可以进行下一步处理。</p> 28 </div> 29 <br /> 30 <div id="panelDiscuss"> 31 32 </div> 33 </div> 34 </form> 35 </body> 36 </html>
调用端的代码就比较简单了
在页面只需要引入jquery 、和IceMx.Mvc 。
在调用IceMx.Mvc.Get("Discuss","Face");的时候会载入视图、控制器、模型并且把视图绑定到控制器内部。
这里评论模块儿感觉上像一个组件,因为可以通过控制器来调用整个模块儿,其实控制器就是这个组件的代表,也就实现了组件化。
如果控制器加一些参数配置这个组件就可以适应多种场合了。
总结
这就是我的一个思路和实现步骤,请各位大神指教。
其他
若有兴趣请关注分类下的其他文章,如果能得到您的支持将不甚感激。