iview的table中嵌套input,select等(附带一个添加行,删除行的功能)
最近要做一个table,里边的内容比较特殊,全都是由下拉框和输入框等构成的,看到网上大部分人都是通过用render函数解决的,因为之前使用过iview的可编辑表格功能,是通过slot实现的,尝试着通过slot来
实现了下该功能,相比render,看起来友好多了。
不过还是有缺陷的,可以很明显的看到下边v-model中绑定的值,我并没有从slot-scope中取出,绑定里边的数据。而是选择直接手动绑定了页面的tableData,这是因为我发现如果使用scople中的row的数据绑定,会造成数据没有办法完成双向的绑定,只能完成单向的,造成的结果就是,如果手动修改tableData数组中的值,页面的值会发生改变,但是如果修改了页面的输入框的值,tableData的数据不会发生改变。
具体原因我认为多半是vue的单向数据流造成的,相同的情况之前在封装组件的时候遇到过,之前的解决方法到这里没有办法使用。
如果有高手知道原因或者解决办法,烦请不吝赐教。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>iview example</title> <link rel="stylesheet" type="text/css" href="http://unpkg.com/view-design/dist/styles/iview.css"> <script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script> <script type="text/javascript" src="http://unpkg.com/view-design/dist/iview.min.js"></script> <style type="text/css"> .ivu-table-wrapper{ overflow: visible; } .ivu-table th { text-align: center; } .ivu-table-cell{ text-align: center; } </style> </head> <body> <div id="app"> <i-table :columns="tableHead" :data="tableData"> <template slot-scope="scope" slot="date1"> <date-picker type="datetime" v-model="tableData[scope.index].date1.value" style="width: 150px"> </date-picker> </template> <template slot-scope="scope" slot="date2"> <date-picker type="datetime" v-model="tableData[scope.index].date2.value" style="width: 150px"> </date-picker> </template> <template slot-scope="scope" slot="select1"> <i-select v-model="tableData[scope.index].select1.value" style="width:130px"> <i-option v-for="item in scope.row.select1.cityList" :value="item.value" :key="item.value">{{ item.label }}</i-option> </i-select> </template> <template slot-scope="scope" slot="select2"> <i-select v-model="tableData[scope.index].select2.value" style="width:130px"> <i-option v-for="item in scope.row.select2.cityList" :value="item.value" :key="item.value">{{ item.label }}</i-option> </i-select> </template> <template slot-scope="scope" slot="select3"> <i-select v-model="tableData[scope.index].select3.value" style="width:130px"> <i-option v-for="item in scope.row.select3.cityList" :value="item.value" :key="item.value">{{ item.label }}</i-option> </i-select> </template> <template slot-scope="scope" slot="input1"> <i-input ref="test" v-model="tableData[scope.index].input1.value" style="width: 100px" > </i-input> </template> <template slot-scope="scope" slot="input2"> <i-input v-model="tableData[scope.index].input2.value" style="width: 100px" > </i-input> </template> <template slot-scope="scope" slot="input3"> <i-input v-model="tableData[scope.index].input3.value" style="width: 100px" > </i-input> </template> <template slot-scope="scope" slot="input4"> <i-input v-model="tableData[scope.index].input4.value" style="width: 100px" > </i-input> </template> <template slot-scope="scope" slot="input5"> <i-input v-model="tableData[scope.index].input5.value" style="width: 100px" > </i-input> </template> </i-table> </div> <script> window.vm = new Vue({ el: '#app', data: { tableData: [ /*测试数据一*/ { date1: { value : new Date() }, date2: { value : new Date() }, select1: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' } ], }, select2: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' } ], }, select3: { value:'', cityList: [ { value: 'train', label: '火车' }, { value: 'plane', label: '飞机' }, ], }, input1: { value : '111' }, input2: { value : '111' }, input3: { value : '111' }, input4: { value : '111' }, input5: { value : '111' }, }, /*测试数据二*/ { date1: { value : new Date() }, date2: { value : new Date() }, select1: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' }, ], }, select2: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' }, ], }, select3: { value:'', cityList: [ { value: 'train', label: '火车' }, { value: 'plane', label: '飞机' }, ], }, input1: { value : '222' }, input2: { value : '222' }, input3: { value : '222' }, input4: { value : '222' }, input5: { value : '222' }, }, /*测试数据三*/ { date1: { value : new Date() }, date2: { value : new Date() }, select1: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' }, ], }, select2: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' }, ], }, select3: { value:'', cityList: [ { value: 'train', label: '火车' }, { value: 'plane', label: '飞机' }, ], }, input1: { value : '333' }, input2: { value : '333' }, input3: { value : '333' }, input4: { value : '333' }, input5: { value : '333' }, }, ], tableHead: [{title:"出发日期",slot:"date1",width:"170"},{title:"结束日期",slot:"date2",width:"170"},{title:"出发地",slot:"select1"},{title:"目的地",slot:"select2"},{title:"交通工具",slot:"select3"},{title:"项目代码",slot:"input1"},{title:"出差公司名称及地址",slot:"input2"},{title:"出差目的",slot:"input3"},{title:"随行人员",slot:"input4"},{title:"备注",slot:"input5"}] }, created:function(){ }, methods: { getData : function(){ let that = this; for(let i=0;i<that.tableData.length;i++){ let row = that.tableData[i]; let str = '第'+i+'行的数据为'; for(let key in row){ if(typeof row[key].value != "undefined"){ str += row[key].value+" "; } } console.log(str); } } } }) </script> </body> </html>
代码中,写了一个简单的取数据的方法,运行结果如下图:
另外,基于前边的功能也完成了一个添加一行,删除一行的功能,通过render函数写出来的,代码如下:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>iview example</title> <link rel="stylesheet" type="text/css" href="http://unpkg.com/view-design/dist/styles/iview.css"> <script type="text/javascript" src="http://vuejs.org/js/vue.min.js"></script> <script type="text/javascript" src="http://unpkg.com/view-design/dist/iview.min.js"></script> <style type="text/css"> .ivu-table-wrapper{ overflow: visible; } .ivu-table th { text-align: center; } .ivu-table-cell{ text-align: center; } </style> </head> <body> <div id="app"> <i-table :columns="tableHead" :data="tableData"> <template slot-scope="scope" slot="date1"> <date-picker type="datetime" v-model="tableData[scope.index].date1.value" style="width: 150px"> </date-picker> </template> <template slot-scope="scope" slot="date2"> <date-picker type="datetime" v-model="tableData[scope.index].date2.value" style="width: 150px"> </date-picker> </template> <template slot-scope="scope" slot="select1"> <i-select v-model="tableData[scope.index].select1.value" style="width:130px"> <i-option v-for="item in scope.row.select1.cityList" :value="item.value" :key="item.value">{{ item.label }}</i-option> </i-select> </template> <template slot-scope="scope" slot="select2"> <i-select v-model="tableData[scope.index].select2.value" style="width:130px"> <i-option v-for="item in scope.row.select2.cityList" :value="item.value" :key="item.value">{{ item.label }}</i-option> </i-select> </template> <template slot-scope="scope" slot="input1"> <i-input ref="test" v-model="tableData[scope.index].input1.value" style="width: 100px" > </i-input> </template> <template slot-scope="scope" slot="input2"> <i-input v-model="tableData[scope.index].input2.value" style="width: 100px" > </i-input> </template> <template slot-scope="scope" slot="input3"> <i-input v-model="tableData[scope.index].input3.value" style="width: 100px" > </i-input> </template> </i-table> </div> <script> window.vm = new Vue({ el: '#app', data: { tableData: [ /*测试数据一*/ { date1: { value : new Date() }, date2: { value : new Date() }, select1: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' }, ], }, select2: { value:'', cityList: [ { value: 'train', label: '火车' }, { value: 'plane', label: '飞机' }, ], }, input1: { value : '' }, input2: { value : '' }, input3: { value : '' } }, /*测试数据二*/ { date1: { value : new Date() }, date2: { value : new Date() }, select1: { value:'', cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' }, ], }, select2: { value:'', cityList: [ { value: 'train', label: '火车' }, { value: 'plane', label: '飞机' }, ], }, input1: { value : '' }, input2: { value : '' }, input3: { value : '' } }, ], //表头相关数据 tableHead: [ {title:"出发日期",slot:"date1"}, {title:"结束日期",slot:"date2"}, {title:"出发地",slot:"select1"}, {title:"交通工具",slot:"select2"}, {title:"出差目的",slot:"input1"}, {title:"随行人员",slot:"input2"}, {title:"备注",slot:"input3"}, {title:"操作列"} ] }, created:function(){ //最后一列需要使用render函数加一列,添加数据或删除数据使用 let header = this.tableHead; //列头添加一个+号用于添加行 header[header.length-1].renderHeader = function(column,data){ return column('Icon',{ props: { type: 'md-add' }, style: { fontSize: "25px", fontWeight: "bolder", color: "blue", cursor:"pointer" }, on:{ click:function(){ // 点击事件(新增一行) vm.tblRowAdd(); } } }) } //列头添加一个-号用于删除行 header[header.length-1].render = function(column,data){ return column('Icon',{ props: { type: 'md-remove' }, style: { fontSize: "25px", fontWeight: "bolder", color: "red", cursor:"pointer" }, on:{ click:function(){ // 点击事件(删除一行) vm.tblRowDel(data.index); } } } ) } }, methods: { getData : function(){ let that = this; for(let i=0;i<that.tableData.length;i++){ let row = that.tableData[i]; let str = '第'+i+'行的数据为'; for(let key in row){ if(typeof row[key].value != "undefined"){ str += row[key].value+" "; } } console.log(str); } }, //添加一行的方法 tblRowAdd : function(){ let row = vm.tableData[0]; let newRow = JSON.parse(JSON.stringify(row)); for(let key in newRow){ newRow[key].value = ""; } vm.tableData.push(newRow); }, tblRowDel : function(index){ if(vm.tableData.length<=1){ alert("至少留一行,如果一行都不存在,添加行的方法会有问题!"); return false; } vm.tableData.splice(index,1); } } }) </script> </body> </html>
效果图:
原理很简单,在table绑定的列中添加一列,这一列就是单独为了添加按钮用的,然后通过renderHead来渲染列头,render来渲染每行的末尾,就这样,不懂的可以留言!