最近要做一個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來渲染每行的末尾,就這樣,不懂的可以留言!