从后端到前端之Vue(四)小试牛刀——真实项目的应用(树、tab、数据列表和分页)

阿里 阅读:953 2022-04-14 11:22:51 评论:0

  学以致用嘛,学了这么多,在真实项目里面怎么应用呢?带着问题去学习才是最快的学习方式。还是以前的那个项目,前后端分离,现在把前端换成vue的,暂时采用脚本化的方式,然后在尝试工程化的方式。

  现在先实现功能节点(树)、动态tab、数据列表、分页这几个主要功能。在前面几章里面代码都已经介绍了,好吧分页没说,不过也比较简单了,加个模板,把数据接上,再加个事件就可以了。

一、同一段代码,一个项目里实现多个数据列表

  先看一下效果:GIF动图,1.5s一张不要太着急。另外截图没截好,不太清晰大家多担待。(左上角是一个水印。)

 

二、同样的代码,在实现其他项目实现各种数据列表

  动图里面只演示了两个模块(页面),其实不仅可以实现这两个页面,所有的基础列表页面都可以实现,即使换一个新的项目,也只需要改几个参数就行(不需要修改代码),如下图:

 

三、页面级的抽象

  实现这些功能,(前端)的代码(html+vue)不超过300行(只需要一段,不用各种copy)。首先是vue很给力,代码上面可以做到很精简,另一个就是面向对象的基础——抽象!

  虽然功能模块非常多,但是数据列表的模式是一样的,区别就是——字段不一样,其他的还不都是一样的吗?所以我们可以针对所有的数据列表需求做一个抽象,把共同的功能拿出来做成代码(或者组件),把差异化的需求也拿出来做成json包。这样代码就一样了,不用一次一次的copy。我们只需要维护好json包就可以。

  这么做有几大优点:

1、 减少bug的出现机会,因为代码很少,想出bug都难。而且会经过很多业务模块、项目的测试,可以及时发现bug。

2、 便于修改bug,因为代码就一处,改了一处就是所有(项目)这类的bug都被修改了。

3、 减少了很多代码量,让程序员有更多的时间休息,,,,哦不对,是更多的时间去思考更复杂的业务逻辑如何实现。

4、 便于升级,因为代码只有一处,想要升级修改这一处就好,其他所有的列表功能就都跟着一起升级了。

5、 便于入门学习,就这一处代码,还学不会?

四、完整代码

1、页面、模板 

 1 <html> 
 2 <head> 
 3     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
 4     <title>树和列表以及分页</title> 
 5     <meta charset="utf-8" /> 
 6     <script type="text/javascript" src="vue.js"></script> 
 7     <script type="text/javascript" src="vue-resource.min.js"></script> 
 8     <link type="text/css" rel="stylesheet" media="screen" href="/Manage/css/mangoGlobal.css"> 
 9     <link type="text/css" rel="stylesheet" media="screen" href="/Manage/css/mis-style-p.css"> 
10     <link type="text/css" rel="stylesheet" media="screen" href="/Manage/css/MisStyle_v2.css"> 
11     <link type="text/css" rel="stylesheet" media="screen" href="/Manage/css/debugCss.css"> 
12     <link type="text/css" rel="stylesheet" media="screen" href="/Manage/css/css2.css"> 
13     <script type="text/javascript"> 
14         var dbid = "25,27";    //定义项目标识,区分不同的项目 
15         var dataBaseId = 25; 
16         var projectId = "1,2,3"; 
17     </script> 
18 </head> 
19 <body> 
20     <div id="foo"></div> <!—加载动画--> 
21     <div id="div_Show" class="clearfix"> 
22         <div id="div_logo"> 
23             <span id="showMe"></span>    
24             <span id="webTitle">后台管理 </span> &nbsp; 
25             <span id="exit" onclick="delCookie('saleUserID___')"> 退 出 </span>  
26         </div> 
27         <div style="width:200px;"> 
28             <div >导航菜单</div> 
29             <div id="divTree"> 
30                 <div :key="'tree_' + tree.ModuleID" v-for="tree in trees" v-on:click="treeClick(tree.ModuleID,tree.ModuleName)" v-bind:class="'tree' + tree.ModuleLevel">{{tree.ModuleName}}</div> 
31             </div> 
32         </div> 
33         <div id="div_Main" class="inner"> 
34             <ul id="ulTab" class="tabs left"> 
35                 <li v-for="t in tabs" v-bind:class="{'selectTag':t.isShow}"> 
36                     <a v-on:click="tabClick(t.id)" href="javascript:void(0)"> 
37                        {{t.title}}&nbsp;{{t.id==='1'?tabNumber:''}} 
38                         <em class="arrup" v-on:click.stop="closeTab(t.id)">x</em> 
39                     </a> 
40                 </li> 
41             </ul> 
42             <div id="divIframe"> 
43                <div v-for="t in tabMains" v-bind:class="{'selectTag':t.isShow}" v-show="t.isShow"> 
44                     {{ t.message }} 
45                     <table class="table_default1" style="" v-show="t.message!=='欢迎使用!'"> 
46                         <tr> 
47                             <th v-for="key in t.orderBy"> 
48                                 {{t.tableTh[key].title}} 
49                             </th> 
50                         </tr> 
51                         <tr v-for="(tr,i) in t.dataList"> 
52                             <td v-for="index in t.orderBy" v-bind:align="t.tableTh[index].align"> 
53                                 {{tr[index]}} 
54                             </td> 
55                         </tr> 
56                     </table> 
57                     <!--分页控件--> 
58                     <div id="divQuickPage" v-show="t.message!=='欢迎使用!'"> 
59                         <div id="quickPage"> 
60                             <div id="quickPager" class="pagesize1"> 
61                                 <span class="pagetext1" style="cursor: pointer;"><strong>{{t.pageTurn.recordCount}}</strong>条记录</span> 
62                                 <span class="pagetext1" style="cursor: pointer;"><strong>{{t.pageTurn.pageIndex}}</strong>/<strong>{{t.pageTurn.pageCount}}</strong></span> 
63                                 <span class="pagetext1" style="cursor: pointer;">每页<strong>{{t.pageTurn.pageSize}}</strong>条记录</span> 
64                                 <span id="navi" style="cursor: pointer;"> 
65                                     <a v-for="(p,index) in t.pageTurn.pageCount" v-on:click="naviClick(t.tabId,index+1)">{{index+1}}</a> 
66                                 </span> 
67                                 <a id="first" class="disabled">首页</a> 
68                                 <a id="prev" class="disabled">上一页</a> 
69                                 <a id="next" v-on:click="naviClick(t.tabId,2)">下一页</a> 
70                                 <a id="last">末页</a> 
71                                 <input type="text" id="txtGo" size="3" class="cssTxt"> 
72                                 <a id="spanGo">GO</a> 
73                             </div> 
74                         </div> 
75                     </div> 
76                 </div> 
77             </div> 
78         </div> 
79     </div> 
80  
81     <div id="div_Copyright"> 
82         <span id="divDegub" onclick="DebugShow()">debug</span> <span id="Span1" onclick="DebugCache()">cache</span> 
83         <span id="Span2" onclick="DebugShow()">event</span>  by 自然框架之UI Vue + Json + ashx 
84     </div> 
85 </body>

Vue的代码

 

  1 //树的数据包 
  2     var tree = new Vue({ 
  3         el: '#divTree', 
  4         data: { 
  5             trees: [ 
  6                 { 
  7                     IsHidden: 0, 
  8                     ModuleID: -10, 
  9                     ModuleLevel: 1, 
 10                     ModuleName: "系统管理", 
 11                     ParentID: 0, 
 12                     ParentIDAll: "0", 
 13                     Target: "_self", 
 14                     URL: "#" 
 15                 } 
 16             ] 
 17         }, 
 18         methods: { 
 19             treeClick: function (id,title) { 
 20                 //隐藏前一个的tab 
 21                 var oldId = tab.currentTabId; //记录切换前tab的id 
 22                 tab.beforeTabId = oldId; 
 23                 tab.tabs["tab" + oldId].isShow = false;  //隐藏切换前的tab 
 24                 tabDiv.tabMains["tab" + oldId].isShow = false;  //隐藏切换前的tab容器 
 25                 tab.currentTabId = id;  //记录新的id 
 26                 //创建tab 
 27                 var newTab = { 
 28                     id: id, //标签识别标示 
 29                     title: title, 
 30                     isShow: true, //是否显示 
 31                     message: title 
 32                 }; 
 33  
 34                 //创建tab 的容器 
 35                 var main = { 
 36                     message:title, 
 37                     isShow: true, //是否显示 
 38                     tabId: id //标签识别标示 
 39                 }; 
 40  
 41                 if (typeof (tab.tabs["tab" + id]) === "undefined") 
 42                     tab.tabNumber = tab.tabNumber + 1; 
 43  
 44                 Vue.set(tab.tabs, "tab" + id, newTab); 
 45   
 46                 if (typeof (tabDiv.tabMains["tab" + id]) === "undefined") { 
 47                     //没有加载描述,加载表格的描述信息 
 48                     this.$http.get('/MetaData/GetMeta.ashx?action=grid&mdid=' + id + '&mpvid=' + id + '01&dbid=' + dbid + '&_=1563').then(function (res) { 
 49                         //创建table 
 50                         var table = { 
 51                             message: title, 
 52                             isShow: true, //是否显示 
 53                             tabId: id, //标签识别标示 
 54                             orderBy: [], //可以控制字段的先后顺序,想调整列的先后顺序,改这个数组就行,可以做个性化设置 
 55                             tableTh: {}, //表头的描述信息 
 56                             dataList: [] //数据包,字段名作为关键字,便于列的调整先后顺序 
 57                         }; 
 58  
 59                         for (var key in res.body.data) { 
 60                             var d = res.body.data[key]; 
 61  
 62                             table.tableTh["" + d.ColumnID] = { 
 63                                 title: d.ColName, 
 64                                 align: d.ColAlign 
 65                             }; 
 66                             table.orderBy.push("" + d.ColumnID); 
 67                         } 
 68                         Vue.set(tabDiv.tabMains, "tab" + id, table); 
 69                         //获取数据 
 70                         getDataList(id); 
 71  
 72                     }, function () { 
 73                         console.log('请求表头失败'); 
 74                     }); 
 75                 } else { 
 76                     //获取数据 
 77                     getDataList(id); 
 78                 } 
 79  
 80                 //获取数据 
 81                 function getDataList(id) { 
 82                     tabDiv.$http.get('/Data/GetData.ashx?action=list&mdid=' + id + '&mpvid=' + id + '01&fpvid=' + id + '02&frid=-2&frids=-2&pageno=1&pagerc=0&dbid=' + dbid + '&webappid=1&_=' + Date.now()).then(function (res) { 
 83                         var tableData = tabDiv.tabMains["tab" + id]; 
 84  
 85                         tableData.dataList = res.body.data; 
 86                         tableData.pageTurn = res.body.pageTurn; 
 87                         tableData.isShow = true;  //显示切换前的tab容器 
 88  
 89                         Vue.set(tabDiv.tabMains, "tab" + id, tableData); 
 90  
 91                     }, function () { 
 92                         console.log('请求数据失败'); 
 93                     }); 
 94                 } 
 95             } 
 96         } 
 97     }); 
 98  
 99     //标签的数据包,只有标签,没有标签下面的容器 
100     var tab = new Vue({ 
101         el: '#ulTab', 
102         data: { 
103             tabNumber: 1,       //标签数量,这个是临时的,便于自动重新绑定 
104             currentTabId: 1,    //当前激活的tab的id 
105             beforeTabId: 1,     //上一个被激活的tab的id 
106             tabs: { 
107                 tab1: { //可以有多个标签, 
108                     id: "1", //标签识别标示 
109                     title: "我的桌面", 
110                     isShow: true,        //是否显示 
111                     message: '桌面' 
112                 } 
113             } 
114         }, 
115         methods: { 
116             tabClick: function (id) { 
117                 //切换tab 
118                 var oldId = tab.currentTabId; //记录切换前tab的id 
119                 tab.beforeTabId = oldId; 
120                 tab.tabs["tab" + oldId].isShow = false;  //隐藏切换前的tab 
121                 tabDiv.tabMains["tab" + oldId].isShow = false;  //隐藏切换前的tab容器 
122  
123                 tab.currentTabId = id;  //记录切换后的id 
124                 tab.tabs["tab" + id].isShow = true;  //显示切换后的tab 
125                 tabDiv.tabMains["tab" + id].isShow = true;  //显示切换前的tab容器 
126             }, 
127             closeTab: function (id) { 
128                 if (id === "1") { 
129                     alert("这是桌面,建议不要关闭哦:)"); 
130                     return; 
131                 } 
132  
133                 delete tab.tabs["tab" + id]; //不知道有没有更好的办法 
134                 tab.tabNumber = tab.tabNumber - 1; 
135  
136                 //设置“激活”状态 
137                 var oldId = tab.beforeTabId; //上一个激活tab 
138                 var nowId = tab.currentTabId; //现在激活tab 
139  
140                 if (nowId === id) { 
141                     //关掉的是激活tab,需要设置上一个tab为激活状态 
142                     tab.currentTabId = oldId; 
143                     tab.tabs["tab" + oldId].isShow = true; 
144                     tab.beforeTabId = 1; 
145                 } 
146                 else if (oldId === id) { 
147                     //关闭的是上一个激活tab,修改前一个tab的id 
148                     tab.beforeTabId = 1; 
149                  } else { 
150                     //需要强制修改一下,否则不会刷新 
151                     tab.currentTabId = nowId; 
152                 } 
153             } 
154         } 
155     }); 
156  
157     //tab下面的容器的数据包 
158     var tabDiv = new Vue({ 
159         el: '#divIframe', 
160         data: { 
161             tabMains: { 
162                 tab1: { //可以有多个标签, 
163                     message: '欢迎使用!', 
164                     isShow: true,        //是否显示 
165                     tabId: "1",  //标签识别标示 
166                     orderBy: [], //可以控制字段的先后顺序,想调整列的先后顺序,改这个数组就行,可以做个性化设置 
167                     tableTh: {}, //表头的描述信息 
168                     dataList: [], //数据包,字段名作为关键字,便于列的调整先后顺序 
169                     pageTurn: { 
170                         //naviCount: 5, //显示页码数量 
171                         //pageCount: 3, //总页数 
172                         //pageIndex: 1, //当前页数 
173                         //pageSize: 20, //一页记录数 
174                         //recordCount: 58  //总记录数 
175                     } 
176                 } 
177             } 
178         }, 
179         methods: { 
180             naviClick: function(id,pageIndex) { 
181                 tabDiv.$http.get('/Data/GetData.ashx?action=list&mdid=' + id + '&mpvid=' + id + '01&fpvid=' + id + '02&frid=-2&frids=-2&pageno=' + pageIndex + '&pagerc=0&dbid=' + dbid + '&webappid=1&_=' + Date.now()).then(function (res) { 
182  
183                     var tableData = tabDiv.tabMains["tab" + id]; 
184                     tableData.dataList = res.body.data; 
185                     tableData.pageTurn = res.body.pageTurn; 
186      
187                     Vue.set(tabDiv.tabMains, "tab" + id, tableData); 
188  
189                 }, function () { 
190                     console.log('请求数据失败'); 
191                 }); 
192             } 
193         } 
194     }); 
195  
196     //从后端获取树,然后绑定。以前的项目,现成的接口先拿来用了。 
197     tree.$http.get('/MetaData/GetMeta.ashx?action=tree&mdid=0&dbid=25&ProjectID=1,2,3&cacheKey=0&webappid=1&_=15640190').then(function (res) { 
198         tree.trees = res.body.data; //后端的数据直接赋值,然后就自动绑定上了。 
199     }, function () { 
200         console.log('请求失败处理'); 
201     });

总结

1、 因为是初学vue,所以代码还不够规范,有些地方并不是很理想。还有很多需要优化和改进的地方。

2、 关于脚本和工程化。脚本比较简单直接,引用vue.Js就可以开鲁,便于试验自己的想法,而且vue的大部分方法也都是支持脚本方式的,还没学到路由那一块。现在先用脚本的方式来实现,然后在逐步转成工程化的方式。或者保持两种方式共存。这样更灵活吧,反正代码也没多少。

3、 虽然现在代码不多,但是实现的功能类型也不多,只是简单的数据列表,还没加上查询和按钮组,还有更复杂的表单控件。这些功能都加上之后,代码会变得更加的臃肿,也就意味着一步步走向深渊——不可维护、不可扩展。那么怎么办呢?

4、 代码的可维护性——组件化。做成组件的方式来分割代码。Emmmm,不知道vue还有没有更好的方式。总之有好的方法都可以拿来用。

5、 代码的可扩展性,目前tab里面只能放数据列表,还没想到更好的方式放其他类型的内容,以前用了一个粗暴的方式——iframe,想放啥都可以。现在不想用iframe了。

下一步是研究一下表单的问题了。


标签:VUE
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号