Deep Sea for JS
- 作者:
- 苍石
- 进度:
- 测试
- 项目开始时间:
- 2021-03-02
- 项目结束时间:
- 项目发表时间:
- 2021-05-26 16:59:03
- 最后编辑于:
- 4 年前
- 标签:
- 配置框架JAVASCRIPT
Deep-Sea JS
Javascript
中配置动态化、所见即所得的轻量级解决方案
特征
- 动态组合配置
- 支持配置多层级结构复合
- 支持链式属性名
- 支持由内到外的参数供给
解决的问题
在项目开发过程中,每当你定义一个组件或方法,你需要从外部获取很多参数,一两个还好,如果十个甚至二十个三十个参数,我们大多都会采用对象的形式来定义一个参数,然后用这个对象的子属性作为我们需要的参数
// 用对象获取多个参数
function doSomething(options){
const {name, age} = options;
}
当这种方式始终具有几个痛点
- 常量的复用
在一些配置中,可能一个变量会引用到另一个变量比如
Full Name
会用到First Name
和Last Name
, 如果类似的变量有很多并且在同一个配置里就会极尽复杂
如果通过使用// normal const personConfig = { fullName: 'Jason Smith', lastName: 'Smith', firstName: 'Jason' }
Deep-Sea
我们就可以将fullName
声明会动态属性,即function
,动态将firstName
和lastName
相连// deep-sea const personConfig = { fullName: ({firstName,lastName}) => `${firstName} ${lastName}`, lastName: 'Smith', firstName: 'Jason' }
- 使用动态配置时不能直接获取参数值
假设你需要显示一段文字,内容是某一个日期的格式化字符串,在传入的参数中,通常情况下可能是这样的
可以看到,在以上情况下,我们需要在解析配置的地方额外去调用// normal // 声明参数 const dateConfig = { date: new Date(), format: 'yyyy-MM-dd hh:mm:ss' } // 获取文字内容 function getContentText(config){ const {date, format} = config; return formatDate(date, format); }
formatDate
方法并且需要从配置中获取format
参数,如果这个结果需要在多个地方使用,就变得极其繁琐。Deep-Sea
就很好的解决了这个问题
通过使用// normal // 声明参数 const dateConfig = { date: new Date(), shownText: ({date})=>{ return formatDate(date, 'yyyy-MM-dd hh:mm:ss'); }, } // 获取文字内容 function getContentText(config){ const deepSeaConfig = deepSea.configure(config); return deepSeaConfig.shownText; }
Deep-Sea
来加载配置,我们可以直接获取需要显示的参数值,所见即所得,不需要通过参数去写额外的代码再次运算,在多次调用的情况下,Deep-Sea
自带的缓存机制也可以防止代码的多次运算,在开发效率和运行效率上大大提升。 - 在配置时,不能动态地获取到一些来自组件或方法内部的变量
在某些情况下,假设需要配置性别,但是性别是被声明为一个常量并且没有暴露出来,由于无法获取到性别的常量导致无法实现性别相关的配置,但在
Deep-Sea
中,我们可以通过一下方式实现
在function getPersonInfo(config){ const MALE = 1, FEMALE = 0; // 内部的常量无法被外部所获取 return = deepSea.configure(config,{MALE, FEMALE}); // 通过 deep-sea 的 provider 提供给配置方法 } getPersonInfo({ gender: ({MALE}) => MALE // 声明性别为内部的 MALE });
Deep-Sea
中,我们可以提供额外的Provider
用于为配置中的动态属性提供参数,从而更好地达到所见即所得的目的 - 在读取常规配置时,如果有多级对象,经常会遇到
null
异常
如上所示,// 该配置对象没有子对象 const config = { name: 'config' } // 以上配置传入该方法会报错 function getChildName(config){ return config.child.name; } // 使用 deep-sea function getChildNameByDeepSea(config){ const deepSeaConfig = deepSea.configure(config); return deepSeaConfig['child.name']; }
Deep-Sea
支持链式属性用以获取子级对象的属性,如果没有自己对象则返回undefined
快速开始
使用
npm
或yarn
引入核心模块依赖:@deep-sea/core
Live Demo
function demo(expect) {
// 模拟表格配置(列)
const tableConfig = {
columns: [
{
label: '名字',
cell: {
output: ({lastName, firstName}) => lastName + firstName
}
},
{
label: '性别',
cell: {
output({MALE, FEMALE}) {
if (this.gender === MALE) {
return '男'
}
if (this.gender === FEMALE) {
return '女'
}
return '未知'
}
}
},
{
label: '籍贯',
cell: {
output: ({local, $root, $get}) => $get('local.province') + local.$get('city') + $root['local.county']
}
}
]
};
function applyTable(config) {
// 展示个人信息(行)
const rows = [
{
firstName: '三',
lastName: '张',
gender: 0,
local: {
city: '成都',
province: '四川',
county: '高新'
}
},
{
firstName: '思',
lastName: '李',
gender: 1,
local: {
city: '成都',
province: '四川',
county: '华阳'
}
}
];
return configure(
rows.map(row => config.columns.map(column => configure(column, {...row, MALE: 0, FEMALE: 1})))
);
}
const tableResult = applyTable(tableConfig);
expect(tableResult.$get('0.0.label')).toBe('名字');
expect(tableResult.$get('0.1.label')).toBe('性别');
expect(tableResult.$get('0.2.label')).toBe('籍贯');
expect(tableResult.$get('1.0.label')).toBe('名字');
expect(tableResult.$get('1.1.label')).toBe('性别');
expect(tableResult.$get('1.2.label')).toBe('籍贯');
expect(tableResult.$get('0.0.cell.output')).toBe('张三');
expect(tableResult.$get('0.1.cell.output')).toBe('男');
expect(tableResult.$get('0.2.cell.output')).toBe('四川成都高新');
expect(tableResult.$get('1.0.cell.output')).toBe('李思');
expect(tableResult.$get('1.1.cell.output')).toBe('女');
expect(tableResult.$get('1.2.cell.output')).toBe('四川成都华阳');
}
demo(
expect => {
return {
toBe(actual) {
console.assert(expect === actual, 'Assertion Failed', expect, actual)
}
}
}
)
留言 ( 0 )