想出个 R.prop() 的新用法
前情
Vue 项目,组件库用 ant-design-vue@1.7.8。
起因
有个设备管理页面,有表单和表格,表单用于新增或编辑数据,表格用于展示数据。
表单中有一项是设备类型,是下拉选择,用 a-select 就需要一个数组,数组元素要含属性 value 和 label,表格其中一列要显示设备类型。
项目中有存放相关数组,typeOptions 当然就要在这两处地方派上用场了。
最初做法是用 R.find() 在 typeOptions 中找和数据 type 值相同的那一项,再读 label:
export const typeOptions = [
{ value: 'pc', label: '电脑' },
{ value: 'pad', label: '平板' },
{ value: 'phone', label: '手机' },
];
<template>
<a-table :columns="columns" :data-source="tableData" />
</template>
<script>
import * as R from 'ramda';
import { typeOptions } from '@/const/device.js';
export default {
data() {
return {
columns: [
{
title: '设备名称',
dataIndex: 'name',
},
{
title: '设备类型',
dataIndex: 'type',
customRender: text => R.find(R.propEq(text, 'value'), typeOptions).label,
},
],
tableData: [],
};
};
};
</script>
思考
项目中有很多表格,有的列要展示字段值对应的文字,都需要用到 xxxOptions 数组,总用 find() 找到对应的项再读 label 的写法不太美观。
(为啥不美观?个人喜好)
如果能像对象那样,直接读 value,得到 label 就好了。
开工
-
将 xxxOptions 数组指定属性转对象
export const toDic = R.curry( (ps, xs) => R.compose( R.fromPairs, R.map(R.props(ps)) )(xs) ); /** 常见的 xxxOptions 数组属性含 `value`, `label`,也可以指定其他属性为键和值 */ export const toDicValueLabel = toDic(['value', 'label']);比如,设备数据
type值是pc,传入对象后得到电脑:toDicValueLabel(typeOptions); // { pc: '电脑', 'pad': '平板', 'phone': '手机' } -
改造
customRender- customRender: text => R.find(R.propEq(text, 'value'), typeOptions).label, + customRender: R.prop(R.__, toDicValueLabel(typeOptions)),若
label没取到需要备用值,可以用R.propOr:- customRender: text => R.find(R.propEq(text, 'value'), typeOptions).label || '--', + customRender: R.propOr('--', R.__, toDicValueLabel(typeOptions)),
延伸
有时需要判断数据的某个属性值,是否等于期望值。
以前的做法是,读数据的属性值,再判断是否等于期望值,期望值每次参照 xxxOptions 后写死。
比如有个设备申请管理页面:
const auditStatusOptions = [
{ value: 0, label: '待提交' },
{ value: 1, label: '待审核' },
{ value: 2, label: '审核通过' },
{ value: 3, label: '已驳回' },
];
/** 是否已通过审核 */
const isPassed = record => 2 == record.auditStatus;
用上 toDicValueLabel() 之后就在想,期望值如果写成 label 那样的文字,可读性就比用 value 那种数字或单词更强,于是也改了此类函数:
-
读到属性值对应的
labelimport * as R from 'ramda'; import { toDicValueLabel } from '@/util/index.js'; import { auditStatusOptions } from '@/const/device.js'; const isPassed = R.compose( /* 判断函数 */ R.prop(R.__, toDicValueLabel(auditStatusOptions)), R.prop('auditStatus'), ); -
传入函数判断
label是否符合条件const isPassed = R.compose( - /* 判断函数 */ + R.equals('审核通过'), R.prop(R.__, toDicValueLabel(auditStatusOptions)), R.prop('auditStatus'), );
可以根据需求传入函数,若想判断属性值是否属于某一类值可以这样:
const isMobileDevice = R.compose(
R.includes(R.__, ['平板', '手机']),
R.prop(R.__, toDicValueLabel(typeOptions)),
R.prop('type'),
);