>[success] # iview 可编辑表格案例 ~~~ 1.这个案例需要自行安装iview Ui 组件库 2.iview的table 和 ele的table 略有区别,iview的table 组件需要使用render函数去渲染 ~~~ >[info] ## 对iview--table 二次封装的案例 * 实现效果 可以直接改变某列的数据 ![](https://box.kancloud.cn/4fe20db2cdc4bb7f40ff50cc2c690417_1576x291.png) >[danger] ##### 封装的目录结构 ~~~ │ ├── 'components' // 存放组件文件夹 │ │ └── 'edit-table' // 存放对iview 二次封装文件 │ │ └─ 'edit-table.vue' // 对iview-table 组件二次封装自定义组存放位置 │ │ └─ 'index.js' // 入口文件 ~~~ >[danger] ##### 对edit-table.vue 封装 ~~~ 1.再对iview - tbale 进行二次封装的时候,需要简单的看一下api 使用说明 这里将下面需要的主要说明简单提取出来,方便理解 1.1.iview table配置和ele 不同,ele列配置需要我们使用ele-table提供的 'el-table-column' 组件,但iview 只需要你传递配置参数columns 1.2.iview-table 留出render 函数渲染模式的,在定制上更趋于数据驱动 2.组件的参数说明props中: 2.1.columns -- 接受父组件的iview-table 列的配置项 2.2 value -- 接受iview-table数据展示 3.二次封装的设想构建,首先想做一个可编辑列的table,因此需要对我们, 对传入组件进行配置的columns 参数进行二次加工,这里的做法增加一个 配置参数'editable' 来判断当前列是否可以进行编辑 4.是否可以编辑在应该在dom渲染的时候就进行对应的操作因此选 择'mounted' 的生命周期去做操作 5.操作数据 和 实际数据要进行深copy进行区分这里使用了'clonedeep'这个 插件 6.一共向外暴露两个方法一个是input 因为v-model 语法糖原因,所以需要父 子组件相互传递暴露出去 7.一个是'on-edit' 让用户拿到编辑数据 ~~~ ~~~ <template> <Table :columns="insideColumns" :data="value"></Table> </template> <script> import clonedeep from 'clonedeep' export default { name: "edit-table", data(){ return{ insideColumns : [], edittingId:'', edittingContent:"", } }, props: { columns: { type: Array, default: () => [] }, value: { type: Array, default: () => [] }, }, methods:{ handleClick({row, index, column}){ // 保存 if(this.edittingId === `${column.key}_${index}` ){ let tableData = clonedeep(this.value); tableData[index][column.key] = this.edittingContent this.$emit('input',tableData); this.$emit('on-edit',{row, index, column, newValue:this.edittingContent}) this.edittingId = ''; this.edittingContent = ''; }else{ this.edittingContent = row[column.key]; this.edittingId = `${column.key}_${index}` } }, // 利用input 事件保存 input中的新数据 handleInput (newValue) { console.log(newValue) this.edittingContent = newValue; }, handleColumns(){ // iview 的table 和ele 不一样他需要使用render 渲染 // 父传子的时候判断 当前列是否可以编辑 // 如果可以编辑 父传子 进行条件判断'!item.render && item.editable' // 在调用当前列的render 对象进行渲染即可 // 内容和 input 内容应该是二选一 展示,如果之前使用vue语法的时候使用的是v-if v-show 去控制 // 现在使用render 这种渲染的话 我们需要自己写判断条件 const insideColumns = this.columns.map(item=>{ if(!item.render && item.editable){ item.render = (h,{row, index, column})=>{ const isEditting = this.edittingId === `${column.key}_${index}`; // this.edittingContent = row[column.key] return( <div> {isEditting?<i-input value={row[column.key]} style="width:50px" on-input={this.handleInput}></i-input>: <span>{row[column.key]}</span>} <i-button on-click={this.handleClick.bind(this,{row, index, column})}>{isEditting? '保存' : '编辑'}</i-button> </div> ) } return item }else return item; }) this.insideColumns = insideColumns }, }, watch:{ columns(){ this.handleColumns() }, }, mounted(){ this.handleColumns() }, } </script> <style scoped> </style> ~~~ >[danger] ##### 使用 ~~~ 1.editable 是我们自己自定义的配置项 ~~~ ~~~ <template> <div> 111 <edit-table :columns="columns" v-model="tableData" @on-edit="handleEdit"></edit-table> </div> </template> <script> import EditTable from '_c/edit-table' import { getTableData } from '@/api/data' export default { data(){ return{ tableData:[], columns: [ { key: 'name', title: '姓名' }, { key: 'age', title: '年龄', editable: true }, { key: 'email', title: '邮箱', editable: true } ] } }, methods:{ handleEdit({row, index, column, newValue}){ console.log(row, index, column, newValue) } }, components:{ EditTable, }, mounted () { getTableData().then(res => { this.tableData = res }) } } </script> <style scoped> </style> ~~~