iview前端向后端传数据一直转圈_记一次开发过程当中,iview遇到的一些坑以及解决办法...

本文总结了在使用vue2.0+iview3.0开发过程中遇到的一些问题,包括Modal关闭问题、多表单同步验证、Select选中值未更新以及Table相关问题的解决方案,如Switch、Button、Input、Select、Rate、DatePicker等组件的渲染和事件处理。
摘要由CSDN通过智能技术生成

写在开头:本次项目采用的是vue2.0+iview3.0,最近公司没啥事,来总结一下开发过程当中遇到的问题。前端

一、Modal关闭问题vue

需求背景:modal框里面是个form表单,点击肯定以后,先验证form表单,验证经过则关闭modal框,验证不成功则提示用户,不关闭。ajax

问题描述:原本刚开始想经过modal框v-model绑定的值(true或false)来进行控制,手动改以后,报错。后端

解决办法:api

官方iview的modal组件的api里面有个loading属性,可经过控制loading的值来进行控制modal的显示。数组

举例说明:app

注意: refuseLoading刚开始必定要设置为true。less

这样的话就能够解决问题了。iview

衍生出来的问题:当关闭模态框以后,再次打开时,表单数据没有重置,仍是上一次的数据。ide

解决办法:this.$refs[name].resetFields();    重置表单数据,在关闭模态框的时候调用这个方法可解决。

二、同时验证多个表单问题

需求背景:一个页面有多个表单,提交的时候须要验证多个表单,都验证成功才能进行下一步操做

解决办法:用一个数组来存放每一个表单的验证结果(true验证经过,false验证不经过),最后循环这个数组若是值都为true,说明验证经过。

举例说明:页面有3个表单,须要同时验证,主要代码以下:

提交

name:'HelloWorld',

data() {return{

formValidate1: {

name:''},

formValidate2: {

name:''},

formValidate3: {

name:''},

ruleValidate: {

name: [

{ required:true, message: 'The name cannot be empty', trigger: 'blur'}

]

},

arr: []

}

},

methods: {

check(name){//验证表单是否经过

this.$refs[name].validate((valid) =>{if(valid) {this.arr.push(true); //arr 这个数组是用来存放单个表单的验证状态

} else{this.arr.push(false);

}

})

},

submit(){//提交

this.arr = []; //重置数组

//同时验证多个表单

this.check('formValidate1');this.check('formValidate2');this.check('formValidate3');var flag = null;for(var i = 0; i < this.arr.length; i++) {if(this.arr[i]) { //单个表单验证经过,继续验证下个表单

flag = true;continue;

}else { //单个表单验证不经过,结束

flag = false;break;

}

}if(flag){ //验证表单成功

alert("验证成功");

}else{

alert("验证失败")

}

}

}

}

三、Select 内的 Option 动态改变时,有时选中值未更新的问题

需求背景:Select的下拉数组是由后台返回的,选中的值也是后台返回的。正确赋值以后,select选中的值未更新。

解决办法:刚开始一直在不停的调试,有时候可能正确显示,有时候又不行。这个随机事件真的。。。。最后查阅官方文档,好吧,这是官方的坑,更新到iview最新版本后,问题得以解决。

这也给我之后很好的警示,有时候一些异常状况,能够先看哈官方的更新日志,由于咱们刚开始作项目的时候,版本只是当时的最新版,一些问题可能官方后面已经修复了,因此应及时更新版本。

4、Table相关问题

(1)render函数的运用

参数解读:

h:  vue  Render函数的别名(全名 createElement)即 Render函数

params: table 该行内容的对象

props:设置建立的标签对象的属性

style:设置建立的标签对象的样式

on:为建立的标签绑定事件

scopedSlots:显示做用域插槽

a、Switch 开关

{

title:"可控开关",

key:"isOpen",

align:"center",

width:100,

render:(h, params)=>{return h('i-switch', {

props: {

value: params.row.isOpen? params.row.isOpen : false, //指定当前是否选中 Boolean类型 (isOpen后端返回字段,根据本身接口返回数据,自行修改)

},

scopedSlots:{

open: ()=> h('span', 'on'), //自定义显示打开时的内容

close: () => h('span', 'off') //自定义显示关闭时的内容

},

on: {/** 触发事件是on-change

* 参数value是回调值 Boolean类型*/

'on-change': (value) =>{this.data[params.index].isOpen = value; //赋值 data:表格数据

}

}

})

}

}

b、Button按钮

{

title:'操做',

key:'action',

width:150,

align:'center',

render: (h, params)=> { //按钮操做

return h('div', [

h('Button', {

props: {

type:'primary',

size:'small'},

style: {//自定义样式

marginRight: '5px'},

on: {//自定义事件

click: () =>{this.show(params.index) //params.index是拿到table的行序列,能够取到对应的表格值

}

}

},'查看'),

h('Button', {

props: {

type:'error',

size:'small'},

on: {

click: ()=>{this.remove(params.index)

}

}

},'删除')

]);

}

}

c、Input 输入框

{

title:"input输入框",

key:"inputText",

align:"center",

render:(h, params)=>{return h('Input', {

props: {

value: params.row.inputText? params.row.inputText : '',

size:'small'},

on: {'on-blur': (event) => { //输入框失去焦点时触发

this.data[params.index].inputText = event.target.value; //赋值 data:表格数据

}

}

});

}

}

d、Select 下拉框

{

title:'select下拉框',

key:'selectText',

align:'center',

render: (h, params)=>{return h('Select',{

props:{

value: params.row.selectText? params.row.selectText : '',

size:'small'},

on: {'on-change':(value) => { //下拉框选定的值

this.data[params.index].selectText =value;

}

}

},/**

* this.selectAction 下拉框Option数组

* selectAction:[

{

value: '01',

name:'select_1'

},

{

value: '02',

name:'select_2'

}

]*/

this.selectAction.map((item) =>{ //下拉选项

return h('Option', {

props: {

value: item.value,

label: item.name

}

})

})

)

}

}

e、Rate评分

{

title:"评分",

key:"rate",

align:"center",

render:(h, params)=>{return h('Rate', {

props: {

value: Number(params.row.rate),//当前 star 数 Number类型

'allow-half': true, //能够选中半星

disabled: false //是否只读

},

on: {'on-change': (value) => { //评分改变时触发

this.data[params.index].rate = value; //赋值 data:表格数据

}

}

})

}

}

f、Img图片

{

title:"头像",

key:"avatar",

align:"center",

width:100,

render:(h, params)=>{return h('Avatar', { //也可用原生img标签代替

style: {

width:'30px',

height:'30px','border-radius': '50%'},

attrs: {

src:'https://i.loli.net/2017/08/21/599a521472424.jpg'}

})

}

}

g、DatePicker时间选择器

{

title:"时间选择器",

key:"date",

align:"center",

render:(h, params)=>{return h('DatePicker', {

props: {

value: params.row.date,

size:'small',

type:'datetime'},

on: {'on-change': (value) => { //输入框失去焦点时触发

this.data[params.index].date = value; //赋值 data:表格数据

}

}

});

}

}

h、对数据进行处理

好比,后端返回时间是时间戳格式,展现给用户看的确定不能是时间戳,这时候就须要咱们对数据进行处理

{

title:"申请年份",

align:"center",

key:"applyDate",

render: (h, params)=>{return h('span', {

},new Date(params.row.applyDate).getFullYear()) //对后端返回的时间戳进行处理,返回页面须要展现的格式

}

}

差很少就总结了这几个,写多了就发现,是同样的模板,直接套到render函数里面就是了。想要更多的学习render函数相关的,能够本身前往官网学习。

完整代码:

name:'HelloWorld',

data() {return{

columns: [//表格列的配置描述

{

title:"头像",

key:"avatar",

align:"center",

width:100,

render:(h, params)=>{return h('Avatar', { //也可用原生img标签代替

style: {

width:'30px',

height:'30px','border-radius': '50%'},

attrs: {

src:'https://i.loli.net/2017/08/21/599a521472424.jpg'}

})

}

},

{

title:"时间选择器",

key:"date",

align:"center",

render:(h, params)=>{return h('DatePicker', {

props: {

value: params.row.date,

size:'small',

type:'datetime'},

on: {'on-change': (value) => { //输入框失去焦点时触发

this.data[params.index].date = value; //赋值 data:表格数据

}

}

});

}

},

{

title:"input输入框",

key:"inputText",

align:"center",

render:(h, params)=>{return h('Input', {

props: {

value: params.row.inputText? params.row.inputText : '',

size:'small'},

on: {'on-blur': (event) => { //输入框失去焦点时触发

this.data[params.index].inputText = event.target.value; //赋值 data:表格数据

}

}

});

}

},

{

title:'select下拉框',

key:'selectText',

align:'center',

render: (h, params)=>{return h('Select',{

props:{

value: params.row.selectText? params.row.selectText : '',

size:'small'},

on: {'on-change':(value) => { //下拉框选定的值

this.data[params.index].selectText =value;

}

}

},/**

* this.selectAction 下拉框Option数组

* selectAction:[

{

value: '01',

name:'select_1'

},

{

value: '02',

name:'select_2'

}

]*/

this.selectAction.map((item) =>{ //下拉选项

return h('Option', {

props: {

value: item.value,

label: item.name

}

})

})

)

}

},

{

title:"申请年份",

align:"center",

key:"applyDate",

render: (h, params)=>{return h('span', {

},new Date(params.row.applyDate).getFullYear()) //对后端返回的时间戳进行处理,返回页面须要展现的格式

}

},

{

title:"可控开关",

key:"isOpen",

align:"center",

width:100,

render:(h, params)=>{return h('i-switch', {

props: {

value: params.row.isOpen? params.row.isOpen : false, //指定当前是否选中 Boolean类型 (isOpen后端返回字段,根据本身接口返回数据,自行修改)

},

scopedSlots:{

open: ()=> h('span', 'on'), //自定义显示打开时的内容

close: () => h('span', 'off') //自定义显示关闭时的内容

},

on: {/** 触发事件是on-change

* 参数value是回调值 Boolean类型*/

'on-change': (value) =>{this.data[params.index].isOpen = value; //赋值 data:表格数据

}

}

})

}

},

{

title:"评分",

key:"rate",

align:"center",

render:(h, params)=>{return h('Rate', {

props: {

value: Number(params.row.rate),//当前 star 数 Number类型

'allow-half': true, //能够选中半星

disabled: false //是否只读

},

on: {'on-change': (value) => { //评分改变时触发

this.data[params.index].rate = value; //赋值 data:表格数据

}

}

})

}

},

{

title:'操做',

key:'action',

width:150,

align:'center',

render: (h, params)=> { //按钮操做

return h('div', [

h('Button', {

props: {

type:'primary',

size:'small'},

style: {//自定义样式

marginRight: '5px'},

on: {//自定义事件

click: () =>{this.show(params.index) //params.index是拿到table的行序列,能够取到对应的表格值

}

}

},'查看'),

h('Button', {

props: {

type:'error',

size:'small'},

on: {

click: ()=>{this.remove(params.index)

}

}

},'删除')

]);

}

}

],

data: [//表格数据

{

inputText:'18',

isOpen:false,

selectText :'02',

rate:4,

date:'2019-02-03 00:08:45',

applyDate:1551835636920},

{

inputText:'',

isOpen:true,

selectText :'01',

rate:1.5,

date:'',

applyDate:1506124800000}

],

selectAction:[

{

value:'01',

name:'select_1'},

{

value:'02',

name:'select_2'}

]

}

},

methods: {

show (index) {//查看

this.$Modal.info({

title:'查看',

content:'查看详情'})

},

remove (index) {//删除

this.data.splice(index, 1);

}

}

}

width:90%;

margin:0auto;

padding: 20px 50px0;

}

View Code

(2)selection的多选来作单选:

经过给 columns 数据设置一项,指定 type: 'selection',便可自动开启多选功能,可是有些产品以为iview的单选效果很差,非要用selection的来作单选。如下是解决方案:

{

title:'选择',

align:'center',

key:'checkBox',

width:80,

render:(h,params)=>{return h('div',[

h('Checkbox',{

props:{

value: params.row.checkBox

},

on:{'on-change':(e)=>{this.data.forEach((item)=>{ //先取消全部对象的勾选,checkBox设置为false

this.$set(item, 'checkBox', false);

});this.data[params.index].checkBox = e; //再将勾选的对象的checkBox设置为true

}

}

})

])

}

}

(3)结合Page分页组件一块儿使用

通常来说,在表格数据比较多的状况下,会对表格进行分页展现

分页通常有2种:前端分页、后端分页。前端分页就是前端一次性拿到全部数据,再对拿到的数据进行分页展现。后端分页就是前端一次只拿一页的数据展现,分页的时候再次请求后端。

mounted(){this.changeTableData();

},

methods: {

changePage(current){//页码改变的回调,返回改变后的页码

this.page.current =current;this.changeTableData();

},

changePageSize(size){//切换每页条数时的回调,返回切换后的每页条数

this.page.current = 1;this.page.size =size;this.changeTableData();

},

changeTableData(){/**

* page定义

* page: {

total: 0, 总数

current: 1, // 当前页码

size: 10 // 每页个数

}

*

*

* data: 表格展现数据

* tableData: 后端返回的全部数据

**/

//前端分页

let _start, _end;

let page= this.page;

_start= (page.current - 1) *page.size;

_end= page.current *page.size;this.data = this.tableData.slice(_start, _end);

page.total= this.tableData.length;//后端分页

//ajax请求后端接口,从新获取数据

}

}

使用了type=index,分页以后,索引仍是从1开始,如何实现累加呢?

使用render函数可解决:

{

title:'序号',

align:'center',

type:'index2',

width:80,

render: (h, params)=>{return h('span', params.index + (this.page.current - 1) * this.page.size + 1);

}

}

在翻页以后,如何记住checkbox多选的选中和未选中状态?

用一个数组checkData来装选中的数据,在每次表格数据改变时,经过比对数据来进行回填选中状态。

methods: {changeSelect(data, val){//选中某个数据

/**

* checkData 多选框选中的数组

* id 每条数据的惟一标识*/

for(let i in this.checkData){if(val.id === this.checkData[i].id){this.checkData.splice(i, 1);break;

}

}this.checkData.push(val);

},

changeSelectCancel(data, val){//取消某个数据

for(let i in this.checkData){if(val.id === this.checkData[i].id){this.checkData.splice(i, 1);break;

}

}

},

changeSelectAll(data){//多选选中

let arr =[];for(let i indata){

let flag= true;for(let y in this.checkData){if(data[i].id === this.checkData[y].id){ //已有数据

flag = false;break;

}else{continue;

}

}if(flag){ //添加新数据

arr.push(data[i]);

}

}this.checkData = this.checkData.concat(arr);

},

changeSelectAllCancel(data){//多选取消

for(let i in this.data){ //取消当前页的内容

for(let y in this.checkData){if(this.data[i].id === this.checkData[y].id){this.checkData.splice(y, 1);break;

}

}

}

},

},

watch:{'data':{

handler:function(newValue, oldValue){this.data =newValue;for(let i in this.data){

let flag= false;for(let y in this.checkData){if(this.data[i].id === this.checkData[y].id){

flag= true;break;

}else{continue;

}

}if(flag){ //回填选中状态

this.data[i]._checked = true;

}else{this.data[i]._checked = false;

}

}

},

deep:true}

}

5、定制iview主题

按照官网,一步一步作的,最后却报错:

那是由于less的版本太高,从新卸载,安装3.0如下的版本(好比2.7.3版本),便可解决问题。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值