先简单说明一下,这个Demo引入的vue,iview的方式是标签引入的,没有用到webpack之类的构建工具...

毕竟公司还在用angularjs+jq.

这也是我第一次写文章,大家看看思路就行了,要是有大佬指点指点就更好了

话不多说,先来个效果图

\"\"

我们再看下极为简单的目录结构

\"\"

IViewEditTable    ## vue+iview 实现的可编辑表格
└── index.html    ## 首页
└── js
 └── editTable.js   ## 首页JS
└── ivew      ## iview相关
└── vue
 ├── axios.min.js   ## axios (ajax)
 ├── util.js    ## 与业务无关的纯工具函数包
 └── vue.min.js   ## vue (2.x)

首页html:

<!DOCTYPE html>
<html  ns=\"http://www.w3.org/1999/xhtml\">
<head>
 <  http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
 < >可编辑表格</ >
 <  href=\"iview/iview.css\" rel=\"external nofollow\" rel=\"stylesheet\" />
</head>
<body style=\"background-color: #f0f3f4;\">
 <div id=\"editTableCtrl\">
 <i-table :loading=\"loading\" border :data=\"dataList\" :columns=\"columnsList\" stripe size=\"small\"></i-table>
 </div>
 <  src=\"vue/axios.min.js\"></ >
 <  src=\"vue/vue.min.js\"></ >
 <  src=\"iview/iview.min.js\"></ >
 <  src=\"vue/util.js\"></ >
 <  src=\"js/editTable.js\"></ >
</body>
</html>

首页没什么说的,都是基本的架子. 这是需要渲染的数据及其说明:

{
 \"Status\": 1,
 \"Total\": 233,
 \"Items\": [{
 \"ID\": 1,
 \"PID\": 3,
 \"PRJCODE\": \"2018-001\",           //项目编号 不可编辑
 \"PRJNAME\": \"淡化海水配套泵站\",         //项目名称 文本输入框
 \"PRJTYPE\": \"基础设施\",           //项目类型 下拉选项
 \"JSUNIT\": \"投资公司\",           //建设单位 文本输入框
 \"FLOW_TYPE_CODE\":\"A02\",           //流程分类 下拉选项,与数据库以code形式交互
 \"DATE_START\": \"2018-12-1\",          //开工时间 日期选择
 \"DATE_END\": \"2019-12-1\",          //竣工时间 日期选择
 \"CONTENT\": \"建设淡化海水配套泵站一座,占地面积约8500平方米\", //建设内容 多行输入框
 \"INVEST_ALL\": \"1000\"           //总投资 数字输入框
 }]
}

还有editTable.js的基本架子,$http是我为了方便在utils最后一行加入的 (angularjs用多了,习惯用\\$http)

Vue.prototype.utils = utils
window.$http = axios

editTable.js :

var vm = new Vue({
 el: \'#editTableCtrl\',
 data: function() {
 return {
  loading: true,
  //表格的数据源
  dataList: [],
  // 列
  columnsList: [],
  // 增加编辑状态, 保存状态, 用于操作数据 避免干扰原数据渲染
  cloneDataList: []
 }
 },
 methods: {
 getData: function() {
  var self = this;
  self.loading = true;
  $http.get(\'json/editTable.txt\').then(function(res) {
  self.dataList = res.data.Items;
  self.loading = false;
  });
 },
 },
 created: function() {
 this.getData();
 }
});

我们再来按照iview的规则编写渲染的列:

//...

   /**
    * @name columnsList (浏览器 渲染的列) 
    * @author catkin
    * @see https://www.iviewui.com/components/table
    * @param 
    * { 
    *  Html : 渲染带有html的表头 列: \'资金<em class=\"blue\" style=\"color:red\">来源</em>\'
    * editable : true,可编辑的列 必须有字段 
    * option  : 渲染的下拉框列表,如果需要与数据库交互的值与显示的值不同,须使用[{value:\'value\',label:\'label\'}]的形式,下面有例子
    * date   : 渲染成data类型 ,可选参数: 
    *       date | daterange: yyyy-MM-dd (默认)
    *       datetime | datetimerange: yyyy-MM-dd HH:mm:ss
    *       year: yyyy
    *       month: yyyy-MM
    * input   : 渲染input类型 ,可选参数为html5所有类型 (额外增加 textarea 属性), 默认text
    * handle  : 数组类型, 渲染操作方式,目前只支持 \'edit\', \'delete\'
    * }
    * @version 0.0.1
    */

columnsList: [{
  width: 80,
  type: \'index\',
   : \'序号\',
  align: \'center\'
}, {
  align: \'center\',
   : \'项目编号\',
  key: \'PRJCODE\'
}, {
  align: \'center\',
   : \'项目名称\',
   Html: \'项目名称 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'PRJNAME\',
  editable: true
}, {
  align: \'center\',
   : \'项目分类\',
   Html: \'项目分类 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'PRJTYPE\',
  option: [\'产业项目\', \'基础设施\', \'民生项目\', \'住宅项目\'],
  editable: true
}, {
  align: \'center\',
   : \'建设单位\',
   Html: \'建设单位 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'JSUNIT\',
  editable: true
}, {
  align: \'center\',
   : \'流程分类\',
   Html: \'流程分类 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'FLOW_TYPE_CODE\',
  option: [{
   value: \'A01\',
   label: \'建筑-出让\'
  }, {
   value: \'A02\',
   label: \'建筑-划拨\'
  }, {
   value: \'B01\',
   label: \'市政-绿化\'
  }, {
   value: \'B02\',
   label: \'市政-管线\'
  }],
  editable: true
}, {
  align: \'center\',
   : \'开工时间\',
   Html: \'开工时间 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'DATE_START\',
  //这里在后面处理的时候会分割成[\'month\',\'yyyy-MM\']的数组,分别代表iview的DatePicker组件选择日期的格式与数据库传过来时页面显示的格式
  date: \'month_yyyy-MM\',  
  editable: true
}, {
  align: \'center\',
   : \'竣工时间\',
   Html: \'竣工时间 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'DATE_END\',
  date: \'month_yyyy-MM\',
  editable: true
}, {
  align: \'center\',
   : \'建设内容\',
   Html: \'建设内容 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'CONTENT\',
  input: \'textarea\',
  editable: true
}, {
  align: \'center\',
   : \'总投资(万元)\',
   Html: \'总投资<br />(万元) <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'INVEST_ALL\',
  input: \'number\',
  editable: true
}, {
   : \'操作\',
  align: \'center\',
  width: 150,
  key: \'handle\',
  handle: [\'edit\', \'delete\']
}]

//...

此时页面应该已经可以渲染出表格了

既然要编辑数据,并且我的需求是整行整行的编辑,而编辑的同时就会同步更新数据,那么问题来了
vue中, 数据更新,视图会随之更新. 想象一下,我在输入框中属于一个值,触发了数据更新,接着又触发了视图更新,那么我每次输入时,这个input都会失焦,毫无用户体验. 所以我们把可编辑的动态内容用cloneDataList渲染,静态显示的用dataList渲染
//...
self.dataList = res.data.Items;
// 简单的深拷贝,虽然map会返回新数组,但是数组元素也是引用类型,不能直接改,所以先深拷贝一份
self.cloneDataList = JSON.parse(JSON.stringify(self.dataList)).map(function(item) {
 // 给每行添加一个编辑状态 与 保存状态, 默认都是false
 item.editting = false;
 item.saving = false;
 return item;
});
//...

接下来,我们要根据columnsList做一次循环判断,根据相应的key写出不同的render函数

//全局添加
//根据value值找出数组中的对象元素
function find InOption(value) {
 return function(item) {
 return item.value === value;
 }
}
//动态添加编辑按钮
var editButton = function(vm, h, currentRow, index) {
 return h(\'Button\', {
 props: {
  size: \'small\',
  type: currentRow.editting ? \'success\' : \'primary\',
  loading: currentRow.saving
 },
 style: {
  margin: \'0 5px\'
 },
 on: {
  click: function() {
  // 点击按钮时改变当前行的编辑状态, 当数据被更新时,render函数会再次执行,详情参考https://cn.vuejs.org/v2/api/#render
  // handleBackdata是用来删除当前行的editting属性与saving属性
  var tempData = vm.handleBackdata(currentRow)
  if (!currentRow.editting) {
   currentRow.editting = true;
  } else {
   // 这里也是简单的点击编辑后的数据与原始数据做对比,一致则不做操作,其实更好的应该遍历所有属性并判断
   if (JSON.stringify(tempData) == JSON.stringify(vm.dataList[index])) {
   console.log(\'未更改\');
   return currentRow.editting = false;
   }
   vm.saveData(currentRow, index)
   currentRow.saving = true;
  }
  }
 }
 }, currentRow.editting ? \'保存\' : \'编辑\');
};
//动态添加 删除 按钮
var deleteButton = function(vm, h, currentRow, index) {
 return h(\'Poptip\', {
  props: {
  confirm: true,
   : currentRow.WRAPDATASTATUS != \'删除\' ? \'您确定要删除这条数据吗?\' : \'您确定要对条数据撤销删除吗?\',
  transfer: true,
  placement: \'left\'
  },
  on: {
  \'on-ok\': function() {
   vm.deleteData(currentRow, index)
  }
  }
 },
 [
  h(\'Button\', {
  style: {
   color: \'#ed3f14\',
   fontSize: \'18px\',
   padding: \'2px 7px 0\',
   border: \'none\',
   outline: \'none\',
   focus: {
   \'-webkit-box-shadow\': \'none\',
   \'box-shadow\': \'none\'
   }
  },
  domProps: {
    : \'删除\'
  },
  props: {
   size: \'small\',
   type: \'ghost\',
   icon: \'android-delete\',
   placement: \'left\'
  }
  })
 ]);
};


//methods中添加
init: function() {
 console.log(\'init\');
 var self = this;
 self.columnsList.forEach(function(item) {
 // 使用$set 可以触发视图更新
 // 如果含有 Html属性 将其值填入表头
 if (item. Html) {
  self.$set(item, \'renderHeader\', function(h, params) {
  return h(\'span\', {
   domProps: {
   innerHTML: params.column. Html
   }
  });
  });
 }
 // 如果含有操作属性 添加相应按钮
 if (item.handle) {
  item.render = function(h, param) {
  var currentRow = self.cloneDataList[param.index];
  var children = [];
  item.handle.forEach(function(item) {
   if (item === \'edit\') {
   children.push(editButton(self, h, currentRow, param.index));
   } else if (item === \'delete\') {
   children.push(deleteButton(self, h, currentRow, param.index));
   }
  });
  return h(\'div\', children);
  };
 }
 //如果含有editable属性并且为true
 if (item.editable) {
  item.render = function(h, params) {
  var currentRow = self.cloneDataList[params.index];
  // 非编辑状态
  if (!currentRow.editting) {
   // 日期类型单独 渲染(利用工具暴力的formatDate格式化日期)
   if (item.date) {
   return h(\'span\', self.utils.formatDate(currentRow[item.key], item.date.split(\'_\')[1]))
   }
   // 下拉类型中value与label不一致时单独渲染
   if (item.option && self.utils.isArray(item.option)) {
   // 我这里为了简单的判断了第一个元素为 的情况,其实最好用every来判断所有元素
   if (typeof item.option[0] === \' \') {
    return h(\'span\', item.option.find(find InOption(currentRow[item.key])).label);
   }
   }
   return h(\'span\', currentRow[item.key]);
  } else {
  // 编辑状态
   //如果含有option属性
   if (item.option && self.utils.isArray(item.option)) {
   return h(\'Select\', {
    props: {
    // ***重点***: 这里要写currentRow[params.column.key],绑定的是cloneDataList里的数据
    value: currentRow[params.column.key]
    },
    on: {
    \'on-change\': function(value) {
     self.$set(currentRow, params.column.key, value)
    }
    }
   }, item.option.map(function(item) {
    return h(\'Option\', {
    props: {
     value: item.value || item,
     label: item.label || item
    }
    }, item.label || item);
   }));
   } else if (item.date) {
   //如果含有date属性
   return h(\'DatePicker\', {
    props: {
    type: item.date.split(\'_\')[0] || \'date\',
    clearable: false,
    value: currentRow[params.column.key]
    },
    on: {
    \'on-change\': function(value) {
     self.$set(currentRow, params.column.key, value)
    }
    }
   });
   } else {
   // 默认input
   return h(\'Input\', {
    props: {
    // type类型也是自定的属性
    type: item.input || \'text\',
    // rows只有在input 为textarea时才会起作用
    rows: 3,
    value: currentRow[params.column.key]
    },
    on: {
    \'on-change\'(event) {
     self.$set(currentRow, params.column.key, event.target.value)
    }
    }
   });
   }
  }
  };
 }
 });
},
// 还原数据,用来与原始数据作对比的
handleBackdata: function( ) {
 var clonedData = JSON.parse(JSON.stringify( ));
 delete clonedData.editting;
 delete clonedData.saving;
 return clonedData;
}

到这里完成已经差不多了,补上保存数据与删除数据的函数

// 保存数据
saveData: function(currentRow, index) {
 var self = this;
 // 修改当前的原始数据, 就不需要再从服务端获取了
 this.$set(this.dataList, index, this.handleBackdata(currentRow))
 // 需要保存的数据
 // 模拟ajax
 setTimeout(function() {
 充值编辑与保存状态
 currentRow.saving = false;
 currentRow.editting = false;
 self.$Message.success(\'保存完成\');
 console.log(self.dataList);
 }, 1000)
},
// 删除数据
deleteData: function(currentRow, index) {
 var self = this;
 console.log(currentRow.ID);
 setTimeout(function() {
 self.$delete(self.dataList, index)
 self.$delete(self.cloneDataList, index)
 vm.$Message.success(\'删除成功\');
 }, 1000)
},

完整的editTable.js代码

// 根据数据中下拉的值找到对应的对象
function find InOption(name) {
 return function(item) {
 return item.value === name;
 }
}
var editButton = function(vm, h, currentRow, index) {
 return h(\'Button\', {
 props: {
  size: \'small\',
  type: currentRow.editting ? \'success\' : \'primary\',
  loading: currentRow.saving
 },
 style: {
  margin: \'0 5px\'
 },
 on: {
  click: function() {
   // 点击按钮时改变当前行的编辑状态,当数据被更新时,render函数会再次执行,详情参考https://cn.vuejs.org/v2/api/#render
   // handleBackdata是用来删除当前行的editting属性与saving属性
   var tempData = vm.handleBackdata(currentRow)
   if (!currentRow.editting) {
   currentRow.editting = true;
   } else {
   // 这里也是简单的点击编辑后的数据与原始数据做对比,一致则不做操作,其实更好的应该遍历所有属性并判断
   if (JSON.stringify(tempData) == JSON.stringify(vm.dataList[index])) {
    console.log(\'未更改\');
    return currentRow.editting = false;
   }
   vm.saveData(currentRow, index)
   currentRow.saving = true;
   }
  }
 }
 }, currentRow.editting ? \'保存\' : \'编辑\');
};
//动态添加 删除 按钮
var deleteButton = function(vm, h, currentRow, index) {
 return h(\'Poptip\', {
  props: {
  confirm: true,
   : currentRow.WRAPDATASTATUS != \'删除\' ? \'您确定要删除这条数据吗?\' : \'您确定要对条数据撤销删除吗?\',
  transfer: true,
  placement: \'left\'
  },
  on: {
  \'on-ok\': function() {
   vm.deleteData(currentRow, index)
  }
  }
 },
 [
  h(\'Button\', {
  style: {
   color: \'#ed3f14\',
   fontSize: \'18px\',
   padding: \'2px 7px 0\',
   border: \'none\',
   outline: \'none\',
   focus: {
   \'-webkit-box-shadow\': \'none\',
   \'box-shadow\': \'none\'
   }
  },
  domProps: {
    : \'删除\'
  },
  props: {
   size: \'small\',
   type: \'ghost\',
   icon: \'android-delete\',
   placement: \'left\'
  }
  })
 ]);
};
var vm = new Vue({
 el: \'#editTableCtrl\',
 data: function() {
 return {
  loading: true,
  //表格的数据源
  dataList: [],
  /**
  * @name columnsList (浏览器 渲染的列) 
  * @author ch
  * @see https://www.iviewui.com/components/table
  * @param 
  * { 
  *  Html : 渲染带有html的表头 列: \'资金<em class=\"blue\" style=\"color:red\">来源</em>\'
  * editable : true,可编辑的列 必须有字段 
  * option : 渲染的下拉框列表
  * date  : 渲染成data类型 ,可选参数: 
  *    date | daterange: yyyy-MM-dd (默认)
  *    datetime | datetimerange: yyyy-MM-dd HH:mm:ss
  *    year: yyyy
  *    month: yyyy-MM
  * input  : 渲染input类型 ,可选参数为html5所有类型 (额外增加 textarea 属性), 默认text
  * handle : 数组类型, 渲染操作方式,目前只支持 \'edit\', \'delete\'
  * }
  * @version 0.0.1
  */
  columnsList: [{
  width: 80,
  type: \'index\',
   : \'序号\',
  align: \'center\'
  }, {
  align: \'center\',
   : \'项目编号\',
  key: \'PRJCODE\'
  }, {
  align: \'center\',
   : \'项目名称\',
   Html: \'项目名称 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'PRJNAME\',
  editable: true
  }, {
  align: \'center\',
   : \'项目分类\',
   Html: \'项目分类 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'PRJTYPE\',
  option: [\'产业项目\', \'基础设施\', \'民生项目\', \'住宅项目\'],
  editable: true
  }, {
  align: \'center\',
   : \'建设单位\',
   Html: \'建设单位 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'JSUNIT\',
  editable: true
  }, {
  align: \'center\',
   : \'流程分类\',
   Html: \'流程分类 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'FLOW_TYPE_CODE\',
  option: [{
   value: \'A01\',
   label: \'建筑-出让\'
  }, {
   value: \'A02\',
   label: \'建筑-划拨\'
  }, {
   value: \'B01\',
   label: \'市政-绿化\'
  }, {
   value: \'B02\',
   label: \'市政-管线\'
  }],
  editable: true
  }, {
  align: \'center\',
   : \'开工时间\',
   Html: \'开工时间 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'DATE_START\',
  //这里在后面处理的时候会分割成[\'month\',\'yyyy-MM\']的数组,分别代表iview的DatePicker组件选择日期的格式与数据库传过来时页面显示的格式
  date: \'month_yyyy-MM\',
  editable: true
  }, {
  align: \'center\',
   : \'竣工时间\',
   Html: \'竣工时间 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'DATE_END\',
  date: \'month_yyyy-MM\',
  editable: true
  }, {
  align: \'center\',
   : \'建设内容\',
   Html: \'建设内容 <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'CONTENT\',
  input: \'textarea\',
  editable: true
  }, {
  align: \'center\',
   : \'总投资(万元)\',
   Html: \'总投资<br />(万元) <i class=\"ivu-icon ivu-icon-edit\"></i>\',
  key: \'INVEST_ALL\',
  input: \'number\',
  editable: true
  }, {
   : \'操作\',
  align: \'center\',
  width: 150,
  key: \'handle\',
  handle: [\'edit\', \'delete\']
  }],
  // 增加编辑状态, 保存状态, 用于操作数据 避免干扰原数据渲染
  cloneDataList: []
 }
 },
 methods: {
 getData: function() {
  var self = this;
  self.loading = true;
  $http.get(\'json/editTable.txt\').then(function(res) {
  // 给每行添加一个编辑状态 与 保存状态
  self.dataList = res.data.Items;
  self.cloneDataList = JSON.parse(JSON.stringify(self.dataList)).map(function(item) {
   item.editting = false;
   item.saving = false;
   return item;
  });
  self.loading = false;
  });
 },
 //初始化数据
 //methods中添加
 init: function() {
  console.log(\'init\');
  var self = this;
  self.columnsList.forEach(function(item) {
  // 使用$set 可以触发视图更新
  // 如果含有 Html属性 将其值填入表头
  if (item. Html) {
   self.$set(item, \'renderHeader\', function(h, params) {
   return h(\'span\', {
    domProps: {
    innerHTML: params.column. Html
    }
   });
   });
  }
  // 如果含有操作属性 添加相应按钮
  if (item.handle) {
   item.render = function(h, param) {
   var currentRow = self.cloneDataList[param.index];
   var children = [];
   item.handle.forEach(function(item) {
    if (item === \'edit\') {
    children.push(editButton(self, h, currentRow, param.index));
    } else if (item === \'delete\') {
    children.push(deleteButton(self, h, currentRow, param.index));
    }
   });
   return h(\'div\', children);
   };
  }
  //如果含有editable属性并且为true
  if (item.editable) {
   item.render = function(h, params) {
   var currentRow = self.cloneDataList[params.index];
   // 非编辑状态
   if (!currentRow.editting) {
    // 日期类型单独 渲染(利用工具暴力的formatDate格式化日期)
    if (item.date) {
    return h(\'span\', self.utils.formatDate(currentRow[item.key], item.date.split(\'_\')[1]))
    }
    // 下拉类型中value与label不一致时单独渲染
    if (item.option && self.utils.isArray(item.option)) {
    // 我这里为了简单的判断了第一个元素为 的情况,其实最好用every来判断所有元素
    if (typeof item.option[0] === \' \') {
     return h(\'span\', item.option.find(find InOption(currentRow[item.key])).label);
    }
    }
    return h(\'span\', currentRow[item.key]);
   } else {
    // 编辑状态
    //如果含有option属性
    if (item.option && self.utils.isArray(item.option)) {
    return h(\'Select\', {
     props: {
     // ***重点***: 这里要写currentRow[params.column.key],绑定的是cloneDataList里的数据
     value: currentRow[params.column.key]
     },
     on: {
     \'on-change\': function(value) {
      self.$set(currentRow, params.column.key, value)
     }
     }
    }, item.option.map(function(item) {
     return h(\'Option\', {
     props: {
      value: item.value || item,
      label: item.label || item
     }
     }, item.label || item);
    }));
    } else if (item.date) {
    //如果含有date属性
    return h(\'DatePicker\', {
     props: {
     type: item.date.split(\'_\')[0] || \'date\',
     clearable: false,
     value: currentRow[params.column.key]
     },
     on: {
     \'on-change\': function(value) {
      self.$set(currentRow, params.column.key, value)
     }
     }
    });
    } else {
    // 默认input
    return h(\'Input\', {
     props: {
     // type类型也是自定的属性
     type: item.input || \'text\',
     // rows只有在input 为textarea时才会起作用
     rows: 3,
     value: currentRow[params.column.key]
     },
     on: {
     \'on-change\'(event) {
      self.$set(currentRow, params.column.key, event.target.value)
     }
     }
    });
    }
   }
   };
  }
  });
 },
 saveData: function(currentRow, index) {
  var self = this;
  // 修改当前的原始数据, 就不需要再从服务端获取了
  this.$set(this.dataList, index, this.handleBackdata(currentRow))
  // 需要保存的数据
  // 模拟ajax
  setTimeout(function() {
  // 重置编辑与保存状态
  currentRow.saving = false;
  currentRow.editting = false;
  self.$Message.success(\'保存完成\');
  console.log(self.dataList);
  }, 1000)
 },
 // 删除数据
 deleteData: function(currentRow, index) {
  var self = this;
  console.log(currentRow.ID);
  setTimeout(function() {
  self.$delete(self.dataList, index)
  self.$delete(self.cloneDataList, index)
  vm.$Message.success(\'删除成功\');
  }, 1000)
 },
 // 还原数据,用来与原始数据作对比的
 handleBackdata: function( ) {
  var clonedData = JSON.parse(JSON.stringify( ));
  delete clonedData.editting;
  delete clonedData.saving;
  return clonedData;
 }
 },
 created: function() {
 this.getData();
 this.init();
 }
});

总结

两三天的时间搞的这些,刚开始也是各种懵逼.期间也试过用插槽来实现,但还是没有这个方法来的清晰(队友都能看懂), 总的来说就是在columnsList自定义一些属性,后面根据这些属性,在render函数里return不同的值,思路还是很简单的.

第一次写文章,并且我也是vue初学者,写的凑合看吧 ^_^ ,欢迎留言指正

本demo 连同之前学习vue时写的demo一起放在的我的github上,欢迎star...

github: https://github.com/catkinmu/vue.js-practice/tree/master/IViewEditTable

参考

vue: render文档
iview
iview admin1.x 版本

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

收藏 打印