(轉) 淘淘商城系列——商品類目選擇的實現

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

相關文章
相關標籤/搜索