【vue】使用render函数渲染table中的数据
注:公司项目,为了引起不必要麻烦,码一下,请见谅。
·
注:公司项目,为了引起不必要麻烦,码一下,请见谅。
代码很长,重复的地方比较多,可以看注释的关键词去找需要的东西
- 第一列 整列全是文字 最简单的渲染
- 第二列 整列全是按钮组件
- 第三列 需要根据数据按照条件去渲染。
- 第四列 存在单选按钮和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>
更多推荐
已为社区贡献2条内容
所有评论(0)