(转) 淘淘商城系列——商品类目选择的实现

http://blog.csdn.net/yerenyuan_pku/article/details/72786989javascript

毛主席讲过:“会当水击三千里,自信人生两百年”。当咱们实现商品列表查询这个功能以后,我相信你们都信心倍增,但这只是走完万里长征的第一步,后面还有嵩山峻岭须要咱们不懈攀登,因此千万不可懈怠人生。本文我就来教你们如何实现商品类目的选择。 
首先,固然仍是启动咱们的zookeeper注册中心,而后启动taotao-manager工程和taotao-manager-web工程,启动后咱们点击”新增商品”,而后点击”选择类目”,打开的对话框是空白的,没有任何信息。这是由于咱们尚未实现该界面的展现。 

咱们仍是从index.jsp页面开始提及,以下图所示,能够看到当咱们点击左侧菜单中的”新增商品”时,是会自动去请求item-add.jsp页面的。咱们在以前就已经实现了展现后台界面的功能。 

咱们下面来看看item-add.jsp页面的代码,咱们从中能够看到,这个页面其实也是个代码片断,”选择类目”按钮实际上是个连接,样式为”easyui-linkbutton”,咱们会发现该连接并无指定onclick事件,那么该连接是怎样触发鼠标点击事件的呢?实际上是”.selectItemCat”样式来处理的,咱们在item-add.jsp页面当中搜索会发现并无定义”selectItemCat”,那么它究竟是在哪儿定义的呢?css

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <link href="/js/kindeditor-4.1.10/themes/default/default.css" type="text/css" rel="stylesheet"> <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/kindeditor-all-min.js"></script> <script type="text/javascript" charset="utf-8" src="/js/kindeditor-4.1.10/lang/zh_CN.js"></script> <div style="padding:10px 10px 10px 10px"> <form id="itemAddForm" class="itemForm" method="post"> <table cellpadding="5"> <tr> <td>商品类目:</td> <td> <a href="javascript:void(0)" class="easyui-linkbutton selectItemCat">选择类目</a> <input type="hidden" name="cid" style="width: 280px;"></input> </td> </tr> <tr> <td>商品标题:</td> <td><input class="easyui-textbox" type="text" name="title" data-options="required:true" style="width: 280px;"></input></td> </tr> <tr> <td>商品卖点:</td> <td><input class="easyui-textbox" name="sellPoint" data-options="multiline:true,validType:'length[0,150]'" style="height:60px;width: 280px;"></input></td> </tr> <tr> <td>商品价格:</td> <td><input class="easyui-numberbox" type="text" name="priceView" data-options="min:1,max:99999999,precision:2,required:true" /> <input type="hidden" name="price"/> </td> </tr> <tr> <td>库存数量:</td> <td><input class="easyui-numberbox" type="text" name="num" data-options="min:1,max:99999999,precision:0,required:true" /></td> </tr> <tr> <td>条形码:</td> <td> <input class="easyui-textbox" type="text" name="barcode" data-options="validType:'length[1,30]'" /> </td> </tr> <tr> <td>商品图片:</td> <td> <a href="javascript:void(0)" class="easyui-linkbutton picFileUpload">上传图片</a> <input type="hidden" name="image"/> </td> </tr> <tr> <td>商品描述:</td> <td> <textarea style="width:800px;height:300px;visibility:hidden;" name="desc"></textarea> </td> </tr> <tr class="params hide"> <td>商品规格:</td> <td> </td> </tr> </table> <input type="hidden" name="itemParams"/> </form> <div style="padding:5px"> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="submitForm()">提交</a> <a href="javascript:void(0)" class="easyui-linkbutton" onclick="clearForm()">重置</a> </div> </div> <script type="text/javascript"> var itemAddEditor ; //页面初始化完毕后执行此方法 $(function(){ //建立富文本编辑器 itemAddEditor = TAOTAO.createEditor("#itemAddForm [name=desc]"); //初始化类目选择和图片上传器 TAOTAO.init({fun:function(node){ //根据商品的分类id取商品 的规格模板,生成规格信息。第四天内容。 //TAOTAO.changeItemParam(node, "itemAddForm"); }}); }); //提交表单 function submitForm(){ //有效性验证 if(!$('#itemAddForm').form('validate')){ $.messager.alert('提示','表单还未填写完成!'); return ; } //取商品价格,单位为“分” $("#itemAddForm [name=price]").val(eval($("#itemAddForm [name=priceView]").val()) * 100); //同步文本框中的商品描述 itemAddEditor.sync(); //取商品的规格 /* var paramJson = []; $("#itemAddForm .params li").each(function(i,e){ var trs = $(e).find("tr"); var group = trs.eq(0).text(); var ps = []; for(var i = 1;i<trs.length;i++){ var tr = trs.eq(i); ps.push({ "k" : $.trim(tr.find("td").eq(0).find("span").text()), "v" : $.trim(tr.find("input").val()) }); } paramJson.push({ "group" : group, "params": ps }); }); //把json对象转换成字符串 paramJson = JSON.stringify(paramJson); $("#itemAddForm [name=itemParams]").val(paramJson); */ //ajax的post方式提交表单 //$("#itemAddForm").serialize()将表单序列号为key-value形式的字符串 $.post("/item/save",$("#itemAddForm").serialize(), function(data){ if(data.status == 200){ $.messager.alert('提示','新增商品成功!'); } }); } function clearForm(){ $('#itemAddForm').form('reset'); itemAddEditor.html(''); } </script>
  • 1

咱们可使用Ctrl+H快捷键来打开全文搜素对话框,在”File Search”一栏的下面那个输入框中输入咱们想要搜素的内容,下面指定在哪些类型的文件中搜素,而后点击”Search”。 

搜索完以后,能够看到以下图所示的搜索结果,咱们双击进去。 

能够看到在common.js文件中有关于”.selectItemCat”的事件定义。那么你们可能也注意到了,在item-add.jsp页面当中并无引用common.js文件,为什么能使用这个js文件呢,其实很简单,这是由于在index.jsp页面中引用了该js文件,而item-add.jsp页面只是index.jsp页面的一个代码片断而已,所以能够直接使用index.jsp页面中引用的js文件。 

那么问题来了,这个选择类目按钮是何时被初始化的呢?咱们能够从item-add.jsp下面的js代码中找到答案,以下图所示,能够看到,$(function){}是页面加载完以后会执行的脚本,在这里面有TAOTAO.init方法来初始化类目选择,那么问题又来了,这个TAOTAO又是在哪儿定义的呢? 

其实TAOTAO也是在common.js文件中定义的,以下所示,能够看到TAOTAO中定义了一个init方法,在该方法中调用了this.initItemCat(data);来初始化类目选择组件。 

this.initItemCat(data);所对应的代码以下:html

// 初始化选择类目组件 initItemCat : function(data){ $(".selectItemCat").each(function(i,e){ var _ele = $(e); if(data && data.cid){ _ele.after("<span style='margin-left:10px;'>"+data.cid+"</span>"); }else{ _ele.after("<span style='margin-left:10px;'></span>"); } _ele.unbind('click').click(function(){ $("<div>").css({padding:"5px"}).html("<ul>") .window({ width:'500', height:"450", modal:true, closed:true, iconCls:'icon-save', title:'选择类目', onOpen : function(){ var _win = this; $("ul",_win).tree({ url:'/item/cat/list', animate:true, onClick : function(node){ if($(this).tree("isLeaf",node.target)){ // 填写到cid中 _ele.parent().find("[name=cid]").val(node.id); _ele.next().text(node.text).attr("cid",node.id); $(_win).window('close'); if(data && data.fun){ data.fun.call(this,node); } } } }); }, onClose : function(){ $(this).window("destroy"); } }).window('open'); }); }); }, 
  • 1

咱们能够看到$(".selectItemCat").each(function(i,e){这行代码,为什么要用each来循环呢?这是由于使用.selectItemCat样式的地方可能不止一处,这样初始化就不能只初始化一处,而是应该把全部用到该样式的地方都进行初始化,i是遍历的第几个元素,e是指被遍历的对象,var _ele = $(e);的做用是把原生dom对象转换为jQuery对象,这样就能直接使用jQuery的方法了。_ele.unbind('click').click(function(){的意思是先进行解绑,而后再进行绑定,其中渲染了一个window窗口对象:java

  • 设置了宽(width)和高(height)。
  • modal:true,是指是否使用模态(就是咱们打开对话框以后,后面是灰色的背景,不能操做,只能操做当前打开的对话框),true就是使用的意思。
  • closed:true,的意思是节点是不是闭合的,若是节点下面还有节点,那么默认就应该是闭合的,若是没有子节点了,那么就应该是展开的。
  • onPen是当窗口要打开时候触发的函数,其中有url:'/item/cat/list',这句代码的意思是,会向这个地url址请求窗口中的数据源。

当咱们发送url请求后,那么服务器应该返回什么样的数据呢?最后展现商品分类列表时,须要使用EasyUI的异步树控件展现,咱们可从EasyUI的API中能够看到,返回的数据是对象的json数组,节点必须有的属性是id、text、state,children无关紧要。id是节点的ID,text是节点的名称,state表明节点是否展开,若是节点下有子节点,那么state就为“closed”,若是没有子节点,那么state就为“open”。 

下面咱们来看看咱们的数据库中存储商品分类的表以及存储的数据,以下图所示,能够看到该表有id、parent_id、name、status、sort_order、is_parent等字段,其中parent_id是用来表示树形关系的,is_parent表示是否是父节点,1表示是父节点,0表示是叶子节点。咱们在上图中知道了要展现树形结构数据,须要有固定的三个字段,分别是id、text和state,那么对应到数据库中的字段即是id、name、is_parent三个字段。 

下面咱们在taotao-common工程中新建一个pojo类——EasyUITreeNode.java,该pojopojo用来描述tree的节点信息,包含三个属性id、text、state,以下图所示。 

因为该类要在服务端和客户端之间传输,所以必定要实现序列化接口。 
写完了pojo类,咱们再看看Dao层,因为是单表查询,所以咱们使用逆向工程自动生成的代码就能够,所以Dao层不用写。既然Dao层不用写,咱们直接看Service层,咱们须要新建一个ItemCatService接口类并定义一个方法,以下图所示。 

下面咱们来新建ItemCatService接口的实现类,以下图所示。 

因为新增了服务实现类,所以咱们须要在applicationContext-service.xml配置文件中发布dubbo服务,即声明须要暴露的服务接口,以下图所示。 

服务端写完以后,咱们下面来写springmvc客户端,咱们建立一个ItemCatController类,以下图所示。因为parentId与所传递过来的参数id名称不一致,所以须要使用@RequestParam(name="id")来关联起来,因为刚开始的时候是不传id参数的,所以须要给id一个默认值”0”,也即defaultValue="0"。 

注意,ItemCatController类中添加获取分类节点方法上面有这样一个注解——@RequestMapping("/item/cat/list"),这个注解中的请求路径是从咱们common.js的窗口打开事件中访问的地址复制而来的,以下图所示。 

咱们还能够经过控制台提示的信息找到请求的路径,以下图所示。 

既然在服务端使用dubbo发布了ItemCatService服务,那么在客户端咱们便须要使用dubbo引用下该服务,方法是在springmvc.xml文件中进行引用,以下图所示。 

最后咱们从新打包taotao-common、taotao-manager-interface工程到本地仓库,而后再重启taotao-manager和taotao-manager-web工程,这时再点击”选择类目”,这时即可以看到商品分类了,以下图所示。 

咱们能够经过浏览器的控制台查看具体的请求及返回信息,咱们发现第一次访问时并无带id的信息,以下图所示。 

当咱们展开”钟表”分类时,以下图所示,能够看到,此次访问便带上了参数id=290,这个id是从表单直接传递过来的。 

这样咱们便实现了商品分类的展现及选择。node

相关文章
相关标签/搜索