【vue】使用render函数渲染table中的数据

设计图
注:公司项目,为了引起不必要麻烦,码一下,请见谅。
代码很长,重复的地方比较多,可以看注释的关键词去找需要的东西

  1. 第一列 整列全是文字 最简单的渲染
  2. 第二列 整列全是按钮组件
  3. 第三列 需要根据数据按照条件去渲染。
  4. 第四列 存在单选按钮和input框互动
<template>
  <div>
    <Tabs type="card">
      <TabPane label="选项卡A">
        <div class="fill-table-container">
          <Table border :columns="columns" :data="data" :loading="tableLoading"> </Table>
        </div>
      </TabPane>
      <TabPane label="选项卡B"> </TabPane>
    </Tabs>
  </div>
</template>

<script>
import {Table} from 'view-design';
import Tabs from '../../../components/tabs/index';
import * as wardApi from '../../../api/ward';
import {deepCopy} from 'view-design/src/utils/assist.js';
// 建议先看一下前置知识点
// 渲染函数 & JSX   https://cn.vuejs.org/v2/guide/render-function.html
export default {
  name: 'alarm-setting',
  components: {
    Table,
    Tabs,
  },
  watch: {
    // 深度监听数据变化,主要作用于单选框改变value之后,及时刷新选中样式
    data: {
      handler(newVal, oldVal) {},
      immediate: true,
      deep: true,
    },
  },
  data() {
    return {
      wardId: '',
      tableLoading: true,
      physicalSignsData: {},
      data: [],
      columns: [
        // 第一列 整列全是文字  最简单的渲染
        {
          // title是这一列的标题
          title: '项目',
          key: 'item',
          align: 'center',
          // 此处指定该列的class
          className: 'ivu-table-all table-head-style',
          // render 函数传入两个参数,第一个是 h,第二个是对象,包含 row、column 和 index,分别指当前单元格数据,当前列数据,当前是第几行。
          // 此处渲染,是一行一行的渲染,下面的render是从data绑定的数据里一项一项的拿数据,每一项作为一行中的数据,执行到某一行的时候,这一行的数据就是params.row
          render: (h, params) => {
            // h('div',{},[])   第一个参数是标签,第二个参数是个对象,包含class,style,attrs,on等,第三个参数是数组,包含的是子元素,即嵌套h()
            // 详细介绍见vue官方文档。渲染函数 & JSX   https://cn.vuejs.org/v2/guide/render-function.html
            return h(
              'div',
              {
                style: {
                },
              },
              [
                h(
                  'div',
                  {
                    class: {
                      tableItem: true,
                    },
                    // 注意style的key如果是有连字符,需要写成驼峰的形式,例如:alignItems,justifyContent
                    style: {
                      display: 'inline-block',
                    },
                  },
                  // 第一列,当前行,这一个格子的这个元素中需要放入name这个变量,params.row.name, 
                  params.row.name,
                ),
                // 大的容器中放入两个子元素,两个h('div',{},[])
                h(
                  'div',{},
                  // 还是第一列,还是这一行,这个元素中需要放入unit这个变量,params.row.unit, 
                  params.row.unit,
                ),
              ],
            );
          },
        },
        // 第二列 整列全是按钮组件
        {
          title: '开关',
          key: 'switch',
          render: (h, params) => {
            // 与前面的一样,h的第一个参数可以传入自定义插件
            return h('i-switch', {
              props: {
                value: params.row.enable,
              },
              // on可以传入绑定事件
              on: {
                'on-change': (status) => {
                  this.data[params.row._index].enable = status;
                },
              },
            });
          },
        },
        // 第三列 需要根据数据按照条件去渲染。
        {
          title: '上限下限',
          key: 'threshold',
          className: 'ivu-table-all',
          render: (h, params) => {
            return h('div', {}, [
              h(
                'div',
                {
                  class: {
                    // 这里 是根据后端的数据,如果这个数据是空,当前整个cell就不显示。 这个disappear是display:none
                    tableDisappear: params.row.ruleFormat === 'empty',
                  },
                  // 这里的style当然可以放到css里面一起写。
                  style: {
                    display: 'flex',
                    flexWrap: 'nowrap',                  // 不会换行
                    justifyContent: 'space-around',      // 元素往两边排
                    alignItems: 'center',
                  },
                },
                [
                  h(
                    'div',
                    {
                      class: {
                        // hide是透明度调整为0,disappear是display:none。   此处跟后端约定的是,如果包含upper和lower字段,就显示这个cell,如果只包含upper不包含lower,就把前面的input隐藏,后面input靠右对齐。 
                        tableHide: params.row.ruleFormat.indexOf('lower') === -1,
                        tableDisappear: params.row.ruleFormat.indexOf('upper') === -1 && params.row.ruleFormat.indexOf('lower') === -1,
                      },
                      style: {
                        display: 'inline-block',
                      },
                    },
                    [
                      // 下限 lower
                      h(
                        'div',
                        {
                          style: {
                            display: 'inline-block',
                          },
                        },
                        '下限',
                      ),
                      h(
                        'div',
                        {
                          style: {
                            display: 'inline-block',
                            width: '120px',
                            marginLeft: '24px',
                          },
                        },
                        [
                          h('i-input', {
                            // 限制输入类型必须为number
                            props: {
                              type: 'number',
                            },
                            // input框的双向绑定, attrs里设置value绑定的变量,然后on监听事件,修改value绑定的变量为事件e.target.value;  可自己输出一下e来找到所需要的变量
                            attrs: {
                              value: params.row.rule.lower,
                            },
                            on: {
                              'on-change': (e) => {
                                this.data[params.row._index].rule.lower = e.target.value;
                              },
                            },
                          }),
                        ],
                      ),
                    ],
                  ),
                  // 上限 upper
                  h(
                    'div',
                    {
                      class: {
                        tableHide: params.row.ruleFormat.indexOf('upper') === -1,
                        tableDisappear: params.row.ruleFormat.indexOf('upper') === -1 && params.row.ruleFormat.indexOf('lower') === -1,
                      },
                    },
                    [
                      h(
                        'div',
                        {
                          style: {
                            display: 'inline-block',
                          },
                        },
                        '上限',
                      ),
                      h(
                        'div',
                        {
                          style: {
                            display: 'inline-block',
                            marginLeft: '25px',
                            width: '120px',
                          },
                        },
                        [
                          h('i-input', {
                            props: {
                              type: 'number',
                            },
                            attrs: {
                              value: params.row.rule.upper,
                            },
                            on: {
                              'on-change': (e) => {
                                this.data[params.row._index].rule.upper = e.target.value;
                              },
                            },
                          }),
                        ],
                      ),
                    ],
                  ),
                  // 时间
                  h(
                    'div',
                    {
                      class: {
                        tableDisappear: params.row.ruleFormat.indexOf('time') === -1,
                      },
                      style: {
                        width: '100%',
                        display: 'flex',
                        flexWrap: 'nowrap',
                        justifyContent: 'space-around',
                        alignItems: 'center',
                      },
                    },
                    [
                      h(
                        'div',
                        {
                          props: {},
                          style: {
                            display: 'inline-block',
                          },
                        },
                        [
                          h(
                            'div',
                            {
                              style: {
                                display: 'inline-block',
                              },
                            },
                            '时间',
                          ),
                          h(
                            'div',
                            {
                              style: {
                                display: 'inline-block',
                                width: '120px',
                                marginLeft: '24px',
                              },
                            },
                            [
                              h('i-input', {
                                props: {
                                  type: 'number',
                                },
                                attrs: {
                                  value: params.row.rule.time,
                                },
                                on: {
                                  'on-change': (e) => {
                                    this.data[params.row._index].rule.time = e.target.value;
                                  },
                                },
                              }),
                            ],
                          ),
                        ],
                      ),
                      h(
                        'div',
                        {
                          style: {
                            width: '120px',
                            height: '10px',
                            display: 'inline-block',
                          },
                        },
                        [],
                      ),
                    ],
                  ),
                ],
              ),
            ]);
          },
        },
        // 第四列 存在单选按钮和input框互动    需求变化值或者变化率只能选一个,未选中的那个,input框也会不可用
        {
          title: '变化',
          key: 'changes',
          className: 'ivu-table-all',
          render: (h, params) => {
            return h(
              'div',
              {
                class: {
                  tableDisappear: params.row.ruleFormat.indexOf('change') === -1,
                },
                style: {
                  display: 'flex',
                  flexWrap: 'nowrap',
                  justifyContent: 'space-around',
                  alignItems: 'center',
                  height: '40px',
                },
              },
              [
                h(
                  'div',
                  {
                    style: {
                      display: 'inline-block',
                    },
                  },
                  [
                    h('Radio', {
                      style: {
                        display: 'inline-block',
                      },
                      // 单选框的双向绑定。   网上查了很多联动的方式,试了一下都没效果,然后就用最笨的办法,两个单选分别绑定一个变量,然后点击A单选框,把B单选框绑定的变量设置为false,A自己的变为True,点击B单选框反过来。
                      // 仅仅这样写还不够,点击之后变量被改变了,可是页面上没刷新出来效果,  需要设置watcher进行监听。
                      props: {
                        value: params.row.rule && params.row.rule.change_rate_checked ? params.row.rule.change_rate_checked : false,
                      },
                      on: {
                        'on-change': (e) => {
                          this.data[params.row._index].rule.change_value_checked = false;
                          this.data[params.row._index].rule.change_rate_checked = true;
                        },
                      },
                    }),
                    h(
                      'div',
                      {
                        style: {
                          display: 'inline-block',
                        },
                      },
                      '变化率',
                    ),
                    h(
                      'div',
                      {
                        style: {
                          display: 'inline-block',
                          width: '120px',
                          marginLeft: '8px',
                        },
                      },
                      [
                        h('i-input', {
                          props: {
                            type: 'number',
                            // 绑定单选框的value的变量,判断input框是否可用
                            disabled: !this.data[params.row._index].rule.change_rate_checked,
                          },
                          attrs: {
                            value: params.row.rule.change_rate,
                          },
                          on: {
                            'on-change': (e) => {
                              this.data[params.row._index].rule.change_rate = e.target.value;
                            },
                          },
                        }),
                      ],
                    ),
                    h(
                      'div',
                      {
                        style: {
                          display: 'inline-block',
                          fontWeight: '500',
                          fontSize: '18px',
                          lineHeight: '23px',
                          color: '#555E7A',
                          marginLeft: '8px',
                        },
                      },
                      '%',
                    ),
                  ],
                ),
                h(
                  'div',
                  {
                    props: {},
                    style: {
                      display: 'inline-block',
                    },
                  },
                  [
                    h('Radio', {
                      style: {
                        display: 'inline-block',
                        marginLeft: '24px',
                      },
                      props: {
                        value: params.row.rule && params.row.rule.change_value_checked ? params.row.rule.change_value_checked : false,
                      },
                      on: {
                        'on-change': (e) => {
                          this.data[params.row._index].rule.change_value_checked = true;
                          this.data[params.row._index].rule.change_rate_checked = false;
                        },
                      },
                    }),
                    h(
                      'div',
                      {
                        style: {
                          display: 'inline-block',
                        },
                      },
                      '变化值',
                    ),
                    h(
                      'div',
                      {
                        style: {
                          display: 'inline-block',
                          fontWeight: '500',
                          fontSize: '26px',
                          marginLeft: '20px',
                        },
                      },
                      '±',
                    ),
                    h(
                      'div',
                      {
                        style: {
                          display: 'inline-block',
                          width: '120px',
                          marginLeft: '8px',
                        },
                      },
                      [
                        h('i-input', {
                          props: {
                            type: 'number',
                            disabled: !this.data[params.row._index].rule.change_value_checked,
                          },
                          attrs: {
                            value: params.row.rule.change_value,
                          },
                          on: {
                            'on-change': (e) => {
                              this.data[params.row._index].rule.change_value = e.target.value;
                            },
                          },
                        }),
                      ],
                    ),
                    h(
                      'div',
                      {
                        style: {
                          display: 'inline-block',
                          width: '55px',
                          fontSize: '18px',
                          lineHeight: '27px',
                          textAlign: 'left',
                          color: '#555E7A',
                          marginLeft: '8px',
                        },
                      },
                      params.row.unit,
                    ),
                  ],
                ),
              ],
            );
          },
        },
      ],
    };
  },
  mounted() {
    this.wardId = this.$route.query.wardId;
    this.getPhysicalSigns(this.wardId);
  },
  methods: {
    getPhysicalSigns(wardId) {
      wardApi
        .getPhysicalSigns(wardId)
        .then((res) => {
          this.physicalSignsData = res.data.data;
          this.pushData();
          this.tableLoading = false;
        })
        .catch((err) => {
          this.$Message.error(err.response.data.message);
        });
    },
    savePhysicalSigns(metrics, wardId) {
      wardApi
        .savePhysicalSigns(metrics, wardId)
        .then((res) => {
          console.log(res);
        })
        .catch((err) => {
          this.$Message.error(err.response.data.message);
        });
    },
    pushData() {
      let data = this.physicalSignsData;
      for (let index = 0; index < data.length; index++) {
        if (data[index].rule) {
          // 去掉json里的转义符
          let newJsonStr = data[index].rule.replace(/\\/g, '');
          const newRule = JSON.parse(newJsonStr);
          data[index].rule = {...newRule};
        } else {
          data[index].rule = {change_rate_checked: false, change_value_checked: false, change_rate: 0, change_value: 0};
        }
      }
      this.data = data;
      console.log(this.data);
    },
    handleConfirm() {
      let data = deepCopy(this.data);
      for (let index = 0; index < this.data.length; index++) {
        data[index].rule = JSON.stringify(this.data[index].rule);
      }
      this.savePhysicalSigns(data, this.wardId);
    },
  },
};
</script>
<style lang="less" scoped>
/*表格内某些组件显示隐藏控制*/
.tableHide {
  opacity: 0;
}
.tableDisappear {
  display: none !important;
}
/*input禁用背景色*/
.ivu-input[disabled],
fieldset[disabled] .ivu-input {
  background-color: #303e62;
}
/*input限制输入类型为number时,禁用上下箭头调整数值*/
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
  -webkit-appearance: none;
}
input[type='number'] {
  -moz-appearance: textfield;
}
/*table loading状态时遮罩层背景色*/
.ivu-spin-fix {
  background-color: #181e35;
}
</style>
  • 6
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值