• vue中用js实现循环可编辑表格


    最近项目中需要实现一个很复杂的表格,尝试用组件写,半天写不出来,循环真的好绕,最后直接求助大哥帮我用原生js写了一个。

    大哥巴拉巴拉讲了半天,先这样在那样,问我懂了吗

    我说懂了!

    大哥说那你写吧我看着。

    我打开vs table 停住。

    大哥说 算了我来吧 你看着。

    躺着真好家人们 我是废物。

    表格的需求:

     简单总结一下就是

    1.表格需要动态,根据输入的数字显示列数 

    2.表格可编辑、可禁用、可计算

    其实单纯表格可编辑是比较简单的,主要是根据输入的年份显示对应的内容,就需要对表格进行循环,我用组件循环的时候总是出现整行或者整列数据都一起变的情况,所以需要找到可以编辑单元格的方法。

    经过测试发现这个表格,原来的大哥也是用js写的,并且写死了30年,你输入之后的年份,也只会出现30年的数据。所以我们直接跟他一样!

    我们可以定义一个对象,之后不断地把内容添加进这个对象就可以。

    首先在data中定义一个对象,即初始化的表格对象。

    前两列的表格我们可以直接写死,从合计开始需要进行循环,所以我们直接从合计开始,合计下再分收入和支出,收入和支出的元素直接根据公式来(改成小写是因为后端接收数据不区分大小写,发大写没用)

    还定义了当前年份count,属性名数组keys,和计算的几个公式。

    1. data () {
    2. return {
    3. // 初始化的表格对象
    4. tableData: {
    5. "合计": {
    6. 'income': {
    7. 'a': 0.00,
    8. 'h': 0.00,
    9. 'i': 0.00,
    10. 'j': 0.00,
    11. 'k': 0.00,
    12. 'l': 0.00,
    13. 'm': 0.00,
    14. 'b': '--',
    15. 'n': '--',
    16. 'o': '--',
    17. 'p': '--',
    18. 'q': '--',
    19. 'c': 0.00,
    20. 'r': 0.00,
    21. 's': 0.00,
    22. 't': 0.00,
    23. 'd': '--',
    24. 'u': '--',
    25. 'v': '--',
    26. 'w': '--',
    27. 'x': '--',
    28. 'e': '--',
    29. 'f': '--'
    30. },
    31. 'expend': {
    32. 'a': '--',
    33. 'h': '--',
    34. 'i': '--',
    35. 'j': '--',
    36. 'k': '--',
    37. 'l': '--',
    38. 'm': '--',
    39. 'b': 0.00,
    40. 'n': 0.00,
    41. 'o': 0.00,
    42. 'p': 0.00,
    43. 'q': 0.00,
    44. 'c': '--',
    45. 'r': '--',
    46. 's': '--',
    47. 't': '--',
    48. 'd': 0.00,
    49. 'u': 0.00,
    50. 'v': 0.00,
    51. 'w': 0.00,
    52. 'x': 0.00,
    53. 'e': 0.00,
    54. 'f': 0.00
    55. }
    56. },
    57. },
    58. // 表格对象属性名数组keys
    59. keys: [],
    60. // 填写的年份 默认显示五年
    61. showYear: 5,
    62. // 当前年度
    63. count: new Date().getFullYear(),
    64. // 收入keys a的计算
    65. incomeKeys: ['h', 'i', 'k', 'l', 'm'],
    66. // 支出keys b的计算
    67. expendKeys: ['n', 'o', 'p', 'q'],
    68. // 收入keys c的计算
    69. incomeKeys2: ['r', 's', 't'],
    70. // 支出keys d的计算
    71. expendKeys2: ['u', 'v', 'w', 'x']
    72. }
    73. }

    然后在created中把年份加进去

    1. created() {
    2. // 在created元素周期就要生成表格
    3. let tempAttr = null
    4. // 往tabledata里循环添加30年的数据
    5. for (let i = 0; i < 30; i++) {
    6. tempAttr = this.count + i + ''
    7. this.tableData[tempAttr] = {
    8. 'income': {
    9. 'a': 0.00,
    10. 'h': 0.00,
    11. 'i': 0.00,
    12. 'j': 0.00,
    13. 'k': 0.00,
    14. 'l': 0.00,
    15. 'm': 0.00,
    16. 'b': '--',
    17. 'n': '--',
    18. 'o': '--',
    19. 'p': '--',
    20. 'q': '--',
    21. 'c': 0.00,
    22. 'r': 0.00,
    23. 's': 0.00,
    24. 't': 0.00,
    25. 'd': '--',
    26. 'u': '--',
    27. 'v': '--',
    28. 'w': '--',
    29. 'x': '--',
    30. 'e': '--',
    31. 'f': '--'
    32. },
    33. 'expend': {
    34. 'a': '--',
    35. 'h': '--',
    36. 'i': '--',
    37. 'j': '--',
    38. 'k': '--',
    39. 'l': '--',
    40. 'm': '--',
    41. 'b': 0.00,
    42. 'n': 0.00,
    43. 'o': 0.00,
    44. 'p': 0.00,
    45. 'q': 0.00,
    46. 'c': '--',
    47. 'r': '--',
    48. 's': '--',
    49. 't': '--',
    50. 'd': 0.00,
    51. 'u': 0.00,
    52. 'v': 0.00,
    53. 'w': 0.00,
    54. 'x': 0.00,
    55. 'e': 0.00,
    56. 'f': 0.00
    57. },
    58. // 把年份传给后端 object.values只会获取属性值,所以多加一个year属性
    59. 'year' : tempAttr
    60. }
    61. }
    62. // Object.keys获取对象的属性名赋值给keys
    63. this.keys = Object.keys(this.tableData)
    64. },

    到这里我们表格就循环好了,接下来画表格

    1. "overflowX:scroll; overflowY: scroll;height:350px;">
    2. 收支类别公式合计{{ keys[index - 1] + '年' }}
      {{ index % 2 == 0 ? '支出' : '收入' }}
      一、建设资金来源A=H+I+K+L+M
    3. v-model="tableData['合计'].income.a">
    4. v-model="tableData['合计'].expend.a">
    5. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.a">
    6. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.a">
    7. (一)财政安排资金H
    8. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.h">
    9. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.h">
    10. (二)地方政府专项债券I
    11. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.i">
    12. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.i">
    13. 其中:用于资本金J
    14. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.j">
    15. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.j">
    16. (三)项目单位市场化融资K
    17. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.k">
    18. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.k">
    19. (四)单位自筹资金L
    20. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.l">
    21. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.l">
    22. (五)其他资金M
    23. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.m">
    24. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.m">
    25. 二、项目建设支出B=N+O+P+Q
    26. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.b">
    27. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.b" >
    28. (一)项目建设成本(不含财务费用)N
    29. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.n">
    30. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.n">
    31. (二)财务费用-专项债券付息O
    32. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.o">
    33. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.o">
    34. (三)财务费用-市场化融资付息P
    35. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.p">
    36. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.p">
    37. (四)其他建设支出Q
    38. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.q">
    39. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.q">
    40. 三、项目运营预期收入C=R+S+T
    41. v-model="tableData['合计'].income.c">
    42. v-model="tableData['合计'].expend.c">
    43. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.c">
    44. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.c">
    45. (一)财政补贴收入R
    46. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.r">
    47. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.r">
    48. (二)项目自身经营收入S
    49. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.s">
    50. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.s">
    51. (三)其他收入T
    52. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.t">
    53. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.t">
    54. 四、项目运营支出D=U+V+W+X
    55. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.d">
    56. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.d">
    57. (一)项目运营成本(不含财务费用)U
    58. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.u">
    59. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.u">
    60. (二)财务费用-专项债券付息V
    61. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.v">
    62. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.v">
    63. (三)财务费用-市场化融资付息W
    64. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.w">
    65. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.w">
    66. (四)其他运营支出X
    67. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.x">
    68. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.x">
    69. 五、专项债券还本E
    70. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.e">
    71. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.e">
    72. 六、市场化融资还本F
    73. v-model="tableData[count+ Math.floor((index-1)/2) +''].expend.f">
    74. v-model="tableData[count+ Math.floor((index-1)/2) +''].income.f">
  • 计算方法写在mounted中,这里本来是打算使用watch进行监听的,结果计算出来太慢了,所以就只能直接修改dom节点了。获取所有的compute类进行操作。(本来是直接获取inout框,后来发现这样的话上面的input框也会变化,就加了类)

    1. mounted() {
    2. this.getMajorProject()
    3. // 获取所有class为compute的dom元素节点 遍历监听change事件 当焦点消失的时候数据变化
    4. document.querySelectorAll('.compute').forEach(target => {
    5. target.addEventListener('change', () => {
    6. //年份计算
    7. // A=H+I+K+L+M
    8. for (let i = 0; i < this.showYear; i++) {
    9. this.tableData[this.count + i + ''].income.a=0;
    10. for (let j = 0; j < this.incomeKeys.length; j++) {
    11. console.log(this.incomeKeys[j]+this.tableData[this.count + i + ''].income[this.incomeKeys[j]])
    12. // parseFloat解析字符串返回浮点值
    13. this.tableData[this.count + i + ''].income.a += parseFloat(this.tableData[this.count + i + ''].income[this.incomeKeys[j]])
    14. }
    15. }
    16. // B=N+O+P+Q
    17. for (let i = 0; i < this.showYear; i++) {
    18. this.tableData[this.count + i + ''].expend.b=0;
    19. for (let j = 0; j < this.expendKeys.length; j++) {
    20. console.log(this.expendKeys[j]+this.tableData[this.count + i + ''].expend[this.expendKeys[j]])
    21. this.tableData[this.count + i + ''].expend.b += parseFloat(this.tableData[this.count + i + ''].expend[this.expendKeys[j]])
    22. }
    23. }
    24. // C=R+S+T
    25. for (let i = 0; i < this.showYear; i++) {
    26. this.tableData[this.count + i + ''].income.c=0;
    27. for (let j = 0; j < this.incomeKeys2.length; j++) {
    28. console.log(this.incomeKeys2[j]+this.tableData[this.count + i + ''].income[this.incomeKeys2[j]])
    29. this.tableData[this.count + i + ''].income.c += parseFloat(this.tableData[this.count + i + ''].income[this.incomeKeys2[j]])
    30. }
    31. }
    32. // D=U+V+W+X
    33. for (let i = 0; i < this.showYear; i++) {
    34. this.tableData[this.count + i + ''].expend.d=0;
    35. for (let j = 0; j < this.expendKeys2.length; j++) {
    36. console.log(this.expendKeys2[j]+this.tableData[this.count + i + ''].expend[this.expendKeys2[j]])
    37. this.tableData[this.count + i + ''].expend.d += parseFloat(this.tableData[this.count + i + ''].expend[this.expendKeys2[j]])
    38. }
    39. }
    40. //合计计算
    41. // 先置空
    42. this.tableData['合计'].income.a = 0;
    43. this.tableData['合计'].income.h = 0;
    44. this.tableData['合计'].income.i = 0;
    45. this.tableData['合计'].income.j = 0;
    46. this.tableData['合计'].income.k = 0;
    47. this.tableData['合计'].income.l = 0;
    48. this.tableData['合计'].income.m = 0;
    49. this.tableData['合计'].expend.b = 0;
    50. this.tableData['合计'].expend.n = 0;
    51. this.tableData['合计'].expend.o = 0;
    52. this.tableData['合计'].expend.p = 0;
    53. this.tableData['合计'].expend.q = 0;
    54. this.tableData['合计'].income.c = 0;
    55. this.tableData['合计'].income.r = 0;
    56. this.tableData['合计'].income.s = 0;
    57. this.tableData['合计'].income.t = 0;
    58. this.tableData['合计'].expend.d = 0;
    59. this.tableData['合计'].expend.u = 0;
    60. this.tableData['合计'].expend.v = 0;
    61. this.tableData['合计'].expend.w = 0;
    62. this.tableData['合计'].expend.x = 0;
    63. this.tableData['合计'].expend.e = 0;
    64. this.tableData['合计'].expend.f = 0;
    65. for (let i = 0; i < this.showYear; i++) {
    66. this.tableData['合计'].income.a += parseFloat(this.tableData[this.count + i + ''].income.a);
    67. this.tableData['合计'].income.h += parseFloat(this.tableData[this.count + i + ''].income.h);
    68. this.tableData['合计'].income.i += parseFloat(this.tableData[this.count + i + ''].income.i);
    69. this.tableData['合计'].income.j += parseFloat(this.tableData[this.count + i + ''].income.j);
    70. this.tableData['合计'].income.k += parseFloat(this.tableData[this.count + i + ''].income.k);
    71. this.tableData['合计'].income.l += parseFloat(this.tableData[this.count + i + ''].income.l);
    72. this.tableData['合计'].income.m += parseFloat(this.tableData[this.count + i + ''].income.m);
    73. this.tableData['合计'].expend.b += parseFloat(this.tableData[this.count + i + ''].expend.b);
    74. this.tableData['合计'].expend.n += parseFloat(this.tableData[this.count + i + ''].expend.n);
    75. this.tableData['合计'].expend.o += parseFloat(this.tableData[this.count + i + ''].expend.o);
    76. this.tableData['合计'].expend.p += parseFloat(this.tableData[this.count + i + ''].expend.p);
    77. this.tableData['合计'].expend.q += parseFloat(this.tableData[this.count + i + ''].expend.q);
    78. this.tableData['合计'].income.c += parseFloat(this.tableData[this.count + i + ''].income.c);
    79. this.tableData['合计'].income.r += parseFloat(this.tableData[this.count + i + ''].income.r);
    80. this.tableData['合计'].income.s += parseFloat(this.tableData[this.count + i + ''].income.s);
    81. this.tableData['合计'].income.t += parseFloat(this.tableData[this.count + i + ''].income.t);
    82. this.tableData['合计'].expend.d += parseFloat(this.tableData[this.count + i + ''].expend.d);
    83. this.tableData['合计'].expend.u += parseFloat(this.tableData[this.count + i + ''].expend.u);
    84. this.tableData['合计'].expend.v += parseFloat(this.tableData[this.count + i + ''].expend.v);
    85. this.tableData['合计'].expend.w += parseFloat(this.tableData[this.count + i + ''].expend.w);
    86. this.tableData['合计'].expend.x += parseFloat(this.tableData[this.count + i + ''].expend.x);
    87. this.tableData['合计'].expend.e += parseFloat(this.tableData[this.count + i + ''].expend.e);
    88. this.tableData['合计'].expend.f += parseFloat(this.tableData[this.count + i + ''].expend.f);
    89. }
    90. // 强刷
    91. this.$forceUpdate()
    92. })
    93. })
    94. },

    可编辑的表格就实现了,我们还需要控制表格只能输入数字,这个功能大哥当然是让我自己做,但我项目要的太急还没来得及做,之后有时间实现一下校验的功能。

    接下来是要根据输入的项目年限(图片上写错了)显示对应的列数。其实说是项目年限,其实项目年限是不能填的,项目年限是建设年限和预算年限的合计。

    所以很简单,我们监听一下建设年限和预算年限,做个加法就行。但是问题又来了,项目是用jeecg写的,v-decorator好像不支持监听,我写了没反应,也可能是我不会。那就直接写change事件。

    得到项目期限之后,需要表格跟着变化,其实就把项目期限的值赋给showYear就行。但是可能是因为有了change事件,项目期限不能再写了,所以最后就直接写在建设和预算的change事件里了。

    还有一个注意点是需要使用数字输入框,这样value才是一个值,直接input,每变化一次,内容都会变化。输入10会被当成1和0。

    1. "24" :sm="12">
    2. <a-form-item label="建设期限(年)" :labelCol="labelCol" :wrapperCol="wrapperCol">
    3. <a-input-number style="width:100%;" v-decorator="['constructionPeriod',{initialValue:this.constructionPeriod}]" placeholder="请输入建设期限(年)" @change="changeJsNum" />
    4. a-form-item>
    5. <a-col :xs="24" :sm="12">
    6. <a-form-item label="运营期限(年)" :labelCol="labelCol" :wrapperCol="wrapperCol">
    7. <a-input-number style="width:100%;" v-decorator="['operatingPeriod',{initialValue:this.operatingPeriod}]" placeholder="请输入运营期限(年)" @change="changeYyNum" />
    8. a-form-item>
    9. a-col>
    10. <a-col :xs="24" :sm="12">
    11. <a-form-item label="项目期限(年)" :labelCol="labelCol" :wrapperCol="wrapperCol">
    12. <a-input-number style="width:100%;" v-decorator="['projectPeriod',{initialValue:this.projectPeriod}]" placeholder="请输入项目期限(年)" disabled />
    13. a-form-item>
    14. a-col>
    1. // 建设年限变化
    2. changeJsNum (value) {
    3. // 将值赋给建设年限
    4. if(value === '' || value === null) {
    5. this.constructionPeriod = 0
    6. } else{
    7. this.constructionPeriod = value
    8. }
    9. // 根据预算年限进行项目年限的计算 parseInt:字符串转数字
    10. if(this.operatingPeriod === ''){
    11. this.projectPeriod = parseInt(this.constructionPeriod)
    12. } else {
    13. this.projectPeriod = parseInt(this.constructionPeriod) + parseInt(this.operatingPeriod)
    14. }
    15. // 计算之后 建设或预算年限的value置空(导致项目年限为空)时,项目年限会为字符串0,所以if判断要加上这个
    16. if(this.projectPeriod && this.projectPeriod!='0'){
    17. this.showYear = this.projectPeriod
    18. } else {
    19. this.showYear = 5
    20. }
    21. },
    22. changeYyNum (value) {
    23. if(value === ''|| value === null) {
    24. this.operatingPeriod = 0
    25. } else{
    26. this.operatingPeriod = value
    27. }
    28. if(this.constructionPeriod === ''){
    29. this.projectPeriod = parseInt(this.operatingPeriod)
    30. } else {
    31. this.projectPeriod = parseInt(this.operatingPeriod) + parseInt(this.constructionPeriod)
    32. }
    33. if(this.projectPeriod && this.projectPeriod!='0'){
    34. this.showYear = this.projectPeriod
    35. } else {
    36. this.showYear = 5
    37. }
    38. },

    最后给大家看看我的表格!

     项目年限变化,列数变化。

     

     

  • 相关阅读:
    css高频面试题
    IDEA中.gitignore配置不生效的解决方案
    【图像融合】基于双树复小波变换的像素级图像融合算法附matlab代码
    LaTex 控制图片表格位置[h][t][b][htb]等
    并发原理 — CPU原子性指令(一)
    C++求最大公因数(gcd)的六重境界
    Python - 等待异步函数完成
    【YOLOv5入门】目标检测
    Java多线程进阶——常见的锁策略
    超分辨率硕士论文阅读
  • 原文地址:https://blog.csdn.net/weixin_44320032/article/details/126305496