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来渲染每行的末尾,就这样,不懂的可以留言!

posted @ 2019-12-20 11:19  发飙的蚂蚁  阅读(3498)  评论(0编辑  收藏  举报