摘要:简单点说呢,就是与后端的数据交互和怎么把数据展示出来,用到的资源主要是和,其它参考插件使用。当时,加载中的提示就会出现。后端返回的数据如上图,并不是所有的字段都是可以进行搜索的字段。
1.前言
今天要做的,就是在上一篇文章的基础上,进行功能页面的开发。简单点说呢,就是与后端的数据交互和怎么把数据展示出来,用到的资源主要是element-ui和vue-resource,其它参考(vue-resource插件使用)。今天讲到的一些功能开发,主要就是请求列表数据,详情数据,分页功能操作,搜索,搜索标签等的开发。今天这个,按照下面步骤,一步一步来。一个一个功能的做!
2.数据接口我以‘回款管理’(cashList.vue)为开发的demo,下文讲到的各种增删改查都是在这个文件上操作,大家注意喔!这虽然是做5个功能,其实就只有两个接口。(按照我开发项目,后端提供的接口说明)
2-1分析接口下面分析下我们公司后端给我提供的其中两个接口。而且两个接口都是get请求。
let http_url={ list:"http://xxx.xxx.com/xxx/cash/list", detail:"http://xxx.xxx.com/xxx/cash/detail" } /** http_url.list接口接受参数 ordId //String,订单号 cashId //String.回款编号 custoName //String,客户名称,模糊查询 cashType //int,回款类型 cashStatus //int,回款状态 userName//String,采购人,模糊查询 userMobile //String,采购人电话,模糊查询 //上面是搜索查询的字段,下面是数据的页码和每页的条数 pogeNo //int,页码(必填) pageSize //int,每页显示条数(必填) http_url.detail接口接受参数(按照我开发项目) cashId //String.回款编号(必填) **/2-2整理数据
首先,由于接口http_url.list接口可以接受一些搜索,先把整个准备了!
然后再到页码的一些东西,主要是三个,当前页码,每页条数。(自己随便设的默认值)
数据就变成了
data(){ return { pageSize:10,//每页条数 allCount:0,//记录总数 currentPage:1,//当前页码 cashList: [], //列表数组(现在是准备请求接口,不需要模拟的数据,所以设置一个空数组) keyFrom: {....}//搜索字段 } }
大家可能不明白,同样是请求的参数,页码这些为什么要和搜索字段分开放?之所以分开放是因为页码这些,到下面分页的时候要多带带使用,而且做搜索的时候,页码又不是搜索字段,所以就分开放,下面会详情的说明!
准备就准备这么多了,之后还要用到什么数据,以后再添加!
3.请求列表数据先别急着写,大家可以想下,搜索字段那里,比如我只想根据回款ID(cashId)查询呢?
难道这样发送请求?http://xxx.xxx.com/xxx/cash/l...""&cashId=xxx&custoName=""&cashType=""&cashStatus=""&userName=""&userMobile=""
真没必要,我们想要的是这样http://xxx.xxx.com/xxx/cash/l...
所以,请求之前,先写一个方法,就是过滤搜索字段(keyFrom)里面,值为空的属性。
/** * 清除对象中值为空的属性 */ filterParams(obj){ let _form = obj, _newPar = {}, testStr; //遍历对象 for (let key in _form) { testStr = null; //如果属性的值不为空。 //注意,不要这样判断if (_form[key])。因为有些属性的值可能为0,到时候就会被过滤掉 if (_form[key] !== null && _form[key] !== "") { //把值添加进新对象里面 _newPar[key]=_form[key].toString() } } //返回对象 return _newPar; }3-1请求列表数据
getList(){ //过滤搜索字段值为空的属性,然后对象合并,合并上页码。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { }); }3-2写完之后,在mounted运行这方法。
mounted(){ this.getList(); },
为了能更直观看到结果,我在浏览器直接打开这个接口
需要的有的字段都有了
那么接下来就接收返回的字段
getList(){ //过滤搜索字段值为空的属性,然后对象合并,合并上页码。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { res=res.body; //如果请求成功了,这接口code为0代表请求成功。具体怎样判断还需要看接口 if(res.code===0){ //设置列表数据 this.cashList = res.datas.entityList; } else{ this.$message.error(res.msg); } }); }3-3在html页面铺数据
怎么铺,随机应变呗!
来到el-table这个标签这里。不知道排版布局的话,参考上一篇文章喔!不要不知道我在说什么!
然后开始写
下面简单写几个栗子
3-3-1回款id点击回款id,会出来详情页面(详情页面的方法getDetail我们到下面写,现在)
3-3-2订单id{{scope.row.cashId}}
订单id只需要显示,就简单了
3-3-3回款时间{{ scope.row.ordId }}
回款时间需要把时间戳转成yyyy-mm-dd hh:mm:ss
{{new Date(scope.row.cashDate).toLocaleDateString().replace(///g, "-")}} {{new Date(scope.row.cashDate).toTimeString().split(" ")[0]}}
回款状态需要把状态码转换成文字
3-3-5回款金额待回款 部分回款 已回款 已取消
金额在数据库以分为单位,现在需要转换成元
3-3-6细节优化{{ (scope.row.cashAmount / 100).toFixed(2) }}
好了,典型的几种数据,以及处理的方法,就是在这里了。当然这个只是做展示作用,怎么展示是看项目的需求的!
小伙伴们运行起来的时候,可能会发现两个问题。
1.比如网速比较慢的时候,请求没完成的时候,就会看到这个(这个提醒是element-ui提供的,只要发现cashList是空的,就会出现这个提醒)
如果我们想体验好一点,做一个提示加载中的提示呢
这个简单的。首先在el-table上,设置v-loading="loading"。
然后在data设置loading这个属性
然后就是在请求那里
进入方法的时候,设置loading=true,请求完了再设置成false。(当loading=true时,加载中的提示就会出现。
getList(){ //显示加载中提示 this.loading=true; //过滤搜索字段值为空的属性,然后对象合并,合并上页码。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { res=res.body; //如果请求成功了,这接口code为0代表请求成功。具体怎样判断还需要看接口 if(res.code===0){ //设置列表数据 this.cashList = res.datas.entityList; //关闭加载中提示 this.loading=false; } else{ this.$message.error(res.msg); } }); }
2.再有就是,如果展示的数据,有些是空的字符串,或者是null的话,在列表上就会看到。
这样提示不太友好,因为只显示空白一片,用的人可能不知道怎么回事。这时候加个判断,如果某一个属性的值,为空字符串或者null,就替换成‘--’。
getList(){
//显示加载中提示 this.loading=true; //过滤搜索字段值为空的属性,然后对象合并,合并上页码。 let _par = Object.assign(this.filterParams(this.keyFrom), { pageNo: this.currentPage, pageSize: this.pageSize }); this.$http.get(http_url.list, { params: _par }).then(function (res) { res=res.body; //如果请求成功了,这接口code为0代表请求成功。具体怎样判断还需要看接口 if(res.code===0){ //设置列表数据 this.cashList = res.datas.entityList; this.cashList.map(function (value) { for (let key in value) { //不要if(value[key])判断,有的值可能是0,会把0过滤 if (value[key] === null || value[key] === "") { value[key] = "--" } } }); //关闭加载中提示 this.loading=false; } else{ this.$message.error(res.msg); } }); }
然后我们就会看到这样的结果,就明确的说明了,这里的值为空
4.请求详情数据详情的数据,就是点击列表的任何一条数据,出来一个详情页面。
先在浏览器请求一下(看下有身什么字段,可以方便在html里面铺数据),看到有很多字段。
详情的html现在项目上,用的是这个效果,我们现在也用这个吧!
代码如下,castInfo是在data声明的的变量,作用是储存请求回来的字段,包含字段如上图!
回款金额:{{(castInfo.cashAmount / 100).toFixed(2)}}元
回款编号:{{castInfo.cashId}}|回款日期:{{new Date(castInfo.cashDate).toLocaleDateString().replace(///g, "-") }}
- 回款状态:待回款
- 回款状态:部分回款
- 回款状态:已取消
- 回款状态:已回款
- 概要
基本信息
回款编号 {{castInfo.cashId}} 回款金额 {{(castInfo.cashAmount / 100).toFixed(2)}}元 账户类型 {{castInfo.cashAccountType===1?"公账":"其他账户"}} 其他账户 -- 回款类型 立即回款 定期回款 -- 回款日期 {{new Date(castInfo.cashDate).toLocaleDateString().replace(///g, "-") }} 回款状态 待回款 部分回款 已回款 已取消 -- 回款渠道 支付宝 微信支付 银行转账 苏宁易付宝 易极付 蓝金灵支付 -- 备注 {{castInfo.remark}}
遮罩层和详情div里面的样式我不说了。最外层的样式是下面这样
{ width: 700px; z-index: 1006; position: fixed; top: 0; right: 0; transform: translate3d(700px, 0, 0); height: 100%; background: #535968; transition: transform 1s; }
transform: translate3d(700px, 0, 0);是为了一开始吧它隐藏起来,相信大家都看得懂!怎么让它显示出来呢,把样式改成transform: translate3d(0, 0, 0);这个就行了,动画效果自动会有,因为加了transition: transform 1s;。
请求详情的方法getDetali: function (id) { //contentShow控制详情页和遮罩层的显示,contentClass控制详情页的动画,castInfo为记录请求回来的数据。大家要在data上面声明哦! //也是同样的处理方式,区别就是this.$loading是element提供的全局组件,效果就是整个屏幕显示加载中。 let loadingContent = this.$loading({ text: "正在加载中..." }); //显示详情 this.$http.get(http_url.detail, { params: { cashId: id } }).then(function (res) { res = res.body; if (res.code === 0) { this.castInfo = res.datas.castInfo; //关闭加载中提示 loadingContent.close(); //显示详情的div this.contentShow = true; //为了确保看到动画效果,所以让遮罩层和详情的DIV先显示,再执行this.contentClass = true;让详情DIV从右至左的出现 setTimeout(() => { this.contentClass = true; }) } else { this.$message.error(res.msg); } }); }隐藏详情
既然是详情,又出现,就有隐藏
/** * @description 隐藏详情 */ hideContentDo(){ //先执行this.contentClass = false。让详情DIV从左至右回去,等回去了之后,再执行this.contentShow = false;在隐藏div,否则会看不到动画效果。设置的时间,就是当时动画的时间!transition: transform 1s this.contentClass = false; setTimeout(() => { this.contentShow = false; }, 1000) },5.分页
分页这个功能,大家可能都接触过,写得也是很复杂。但是今天用了element-ui提供的分页组件,就简单多了!
引入分页组件在.cash-table这个DIV下面,直接引入下面的代码
编写分页方法handleCurrentChange这个方法待会写,allCount,pageSize,currentPage这三个变量,都是之前已经声明了的,大家往上翻下就知道了!参数大家看官网-分页
/** * @description 分页处理 * @param val */ handleCurrentChange(val) { //val是组件的返回值,返回当前是第几页 //然后把值赋值给currentPage。 this.currentPage = val; //然后再次调用getList。更新cashList this.getList(); }
这个的代码看着很简单。大家可能会不太理解原理。下面我简单分析下。
1.首先执行this.currentPage = val;获取当前是第几页,比如我点击第二页。this.currentPage的值就是2。
2.然后执行this.getList();。这个时候,在方法里面。
相当于发送了这个请求http://xxx.xxx.com/xxx/cash/l...
然后在执行下去,cashList这个数组就更新了。我们分页就开发完了。
搜索功能这个太常见了,我现在做的项目,搜索需求就是。
然后输入再点击
交互很容易理解。就是输入,然后再输出结果,如上图,我在回款ID下面的文本框输入‘M2017070400060002’。然后点击搜索。就会出现输出结果。
下面,我们一步步来
/** * 显示与隐藏搜索 */ filterSearch(){ //filterModel小伙伴们要在data上声明哦,初始值为false。这个值是记录当前是不是要显示搜索框,进行搜索的。 //当前是否需要搜索状态 if (this.filterModel) { this.cashList.splice(0, 1); } else { this.cashList.unshift({ "cashId": "#", }) } //显示或隐藏搜索 this.filterModel = !this.filterModel; }6-1-3.列表的改造
首先,清楚一个。后端返回的数据(如上图),并不是所有的字段都是可以进行搜索的字段。只有这几个字段(如下图),才可以进行搜索。
所以,这里我分三种请况。
一种情况是,比如回款编号,可以进行搜索的字段。
//修改前{{ scope.row.cashId }}
//修改后{{scope.row.cashId}}
第二种情况是,比如回款状态,可以进行搜索的字段。但是是下拉搜索的
//修改前待回款 部分回款 已回款 已取消 //修改后 待回款 部分回款 已回款 已取消
另一种情况是,比如回款流水号,不可以进行搜索的字段。修改情况是
//修改前6-1-4流程说明{{scope.row.payNo}} //修改后{{scope.row.payNo}}
下面,我简单说明下执行的流程。
1.filterModel这个值,一开始设为false。
2.点击按钮,执行filterSearch,由于filterModel=false;所以最后执行this.cashList.unshift({"cashId": "#"})。
3.this.cashList这个数组,前面就添加了{"cashId": "#"}。
点击前
点击后
4.this.cashList第一条就变成了{"cashId": "#"},表格在遍历到第一条的时候
el-table-column里面,由于**v-if**的关系。排版就改变了!这就是数据驱动的魅力!
是搜索字段的第一行就变成了文本框
不是搜索字段的第一行就变成了空白的
5.交互就实现了!但是有一点要注意,就是搜索框v-model的值一定要绑定正确!
6-2实现搜索功能 6-2-1.首先,在每个按钮里面,都绑定一个点击事件,绑定search方法,用来启动搜索!
这个按钮,大季家都知道是哪个吧!就是这里
/** * 开始搜索 */ search(){ this.getList(); },
没看错,就是这一行,代码,因为每一个文本框v-model了keyFrom相对应的值。所以,只要在文本输入,keyFrom对应的值自动改!然后执行getList,keyFrom中,只要不是空字符或者null。就不会被过滤!这样就相当于执行http://xxx.xxx.com/xxx/cash/l...的请求。至于为什么要令写一个方法,不直接绑定getList呢,因为这里还要触发下面的搜索标签。接下来会下面要说的!
6-3实现重置搜索功能看了搜搜索之后,我想大家都知道重置搜索怎么做了!就是先把keyFrom搜索的属性的值清空,再执行getList。
/** * @description 重置筛选条件 */ resetSearch(){ for (let key in this.keyFrom) { this.keyFrom[key] = null } this.getList(); }7.搜索标签
搜索标签,在很多地方都会见到过,就是给用户看到,执行了什么条件的搜索。
下面就实现下这个功能!
先实现,这个方法,这个方法,我想大家也已经知道了,就是遍历keyFrom,然后把属性和值遍历道一个数组里面,最后在html里面v-for循环一下!
7-2-1添加标签addTags(){ //tagsArr就是存放筛选标签的数组,大家要在data里面设置哦,初始值为[]; let _this = this,_label,_value; //用一个变量,获取清空keyFrom里面值为空的属性! let _params = Object.assign(this.filterParams(this.keyFrom); //用一个变量,获取_params属性的集合! let _paramKeys = Object.keys(_params); //先清空tagsArr, this.tagsArr = []; _paramKeys.forEach((val) => { //根据val,设置_label标签名 swicth(val){ case "cashId":_label="回款编号";break; case "ordId":_label="订单编号";break; case "custoName":_label="客户名称";break; case "cashType":_label="回款类型";break; case "cashStatus":_label="回款状态";break; case "userName":_label="采购人";break; case "userMobile":_label="采购人电话";break; } //然后上面有提到到,比如回款状态,这个的值是下拉搜索的。传过来的值是状态码,并不是文字。我们主要手动把状态码转译成文字 //比如状态吗是0,我们需要转成‘待回款’ //如果val等于cashStatus,就是回款状态,我们需要转译 if (_key === "cashStatus") { //判断状态码 switch (_keyFrom3[_key]) { case "0": _value = "待回款"; break; case "1": _value = "部分回款"; break; case "2": _value = "已回款"; break; case "2": _value = "已取消"; break; } } //tagsArr添加元素! //_value如果为真,就代表是把状态码转成文字的,就添加_value,否则就直接添加_params[val] _this.tagsArr.push({ key: val, label: _label, value: _value||_params[val] }); }); },
这个方法什么时候触发呢,就是在搜索和重置搜索的时候触发 。这也解释了为什么搜索要令写一个方法!
search(){ this.getList(); this.addTags(); }, resetSearch(){ for (let key in this.keyFrom) { this.keyFrom[key] = null } this.getList(); this.addTags(); }
但是大家应该还有注意到一个,就是比如‘回款状态’,是下拉搜索的,所以,在下拉框,就要绑定search方法。
7-2-2html页面遍历然后在html页面遍历这个tagsArr。
眼尖的小伙伴又发现了,tagClose这个方法对吧!
接下来就实现这个!
tagClose(key, _index){ //根据下标,鼠标tagsArr数组某一项 this.tagsArr.splice(_index, 1); //根据key,把keyFrom某一项设为空值 this.keyFrom[key] = null; //重新请求,更新cashList this.getList(); }8.未完待续
好了,今天就到这里了,这篇文章也写了将近10个小时了!如果你有耐心读到这里,你也是很有耐心的勇士!当然,当面的代码和交互还是有细节是需要优化的,这个就比较简单,小伙伴们,随机应变下就知道怎么做了!也写累了!不想说太多了!下一篇文章,预热就是利用监听路由(vue-router)。来实现同一个页面,不同状态的处理。就比如:同样是回款管理,我要求新建一个待回款的页面,但是这个页面只有待回款的数据。回款状态也不能修改!这个小伙伴们也可以试着做下,怎么实现。这个相对简单!
9.往期占坑webpack+vue项目实战(一,搭建运行环境和相关配置)
webpack+vue项目实战(二,开发管理系统主页面)
webpack+vue项目实战(三,配置功能操作页和组件的按需加载)
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/83864.html
摘要:好了,闲话不多说今天要说的时利用监听路由的方式,实现同个页面不同状态的切换。只要等于,那么页面就是待确认回款页面进入待确认回款页面中,回款状态的筛选标签要加上。 1.前言 今天发完这一篇,就要这个系列告一段落了!以后如果有什么要补充的会继续补充!因为在后台管理项目上,搭建的话,主要就是这样了!还有的一些是具体到交互的处理,那个是要根据后端的需求,来进来比较细化的工作,我在这里就不说了!...
摘要:前端日报精选专题之类型判断下百度生态构建发布基于的解决方案将全面支持从绑定,看语言发展和框架设计掘金译机器学习与一付费问答上线,向你心目中的大牛提问吧产品技术日志中文第期团队技术信息流建设翻译基于路由的异步组件加载个必备的装逼 2017-07-06 前端日报 精选 JavaScript专题之类型判断(下) · Issue #30 · mqyqingfeng/Blog 百度Web生态构...
摘要:说起,其实早在出现之前,网页就是在服务端渲染的。没有涉及流式渲染组件缓存对的服务端渲染有更深一步的认识,实际在生产环境中的应用可能还需要考虑很多因素。选择的服务端渲染方案,是情理之中的选择,不是对新技术的盲目追捧,而是一切为了需要。 作者:威威(沪江前端开发工程师)本文原创,转载请注明作者及出处。 背景 最近, 产品同学一如往常笑嘻嘻的递来需求文档, 纵使内心万般拒绝, 身体倒是很诚实...
摘要:前言记录自己从基础学习实战,初入发表文章,望各位大佬口下留情不对之处还请大佬指点一下。在加载完后,你自己默认的浏览器自动打开配置界面新建项目。 1. 前言 记录自己从基础学习vue实战,初入发表文章,望各位大佬口下留情!不对之处还请大佬指点一下。 2. 新建,配置项目 1. 新建Vue-cli3.0脚手架的项目 在这里普及一下,什么是Vue-cli? Vue是一套用于构建用户界面的渐...
摘要:前言记录自己从基础学习实战,初入发表文章,望各位大佬口下留情不对之处还请大佬指点一下。在加载完后,你自己默认的浏览器自动打开配置界面新建项目。 1. 前言 记录自己从基础学习vue实战,初入发表文章,望各位大佬口下留情!不对之处还请大佬指点一下。 2. 新建,配置项目 1. 新建Vue-cli3.0脚手架的项目 在这里普及一下,什么是Vue-cli? Vue是一套用于构建用户界面的渐...
阅读 1406·2021-11-24 10:20
阅读 3648·2021-11-24 09:38
阅读 2293·2021-09-27 13:37
阅读 2195·2021-09-22 15:25
阅读 2269·2021-09-01 18:33
阅读 3487·2019-08-30 15:55
阅读 1782·2019-08-30 15:54
阅读 2080·2019-08-30 12:50