# JS **Repository Path**: Kinyx/js ## Basic Information - **Project Name**: JS - **Description**: K framework @ JavaScript - **Primary Language**: JavaScript - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2024-11-15 - **Last Updated**: 2024-11-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 目标 + 一、轻量级 无论是`页面文本`、`数据`、`JS`、`CSS`、`图片`,所有网络请求都尽可能降至最低。为初创公司减少服务器配置压力。 + 1、`页面文本`: 所有非固定的页面内容,都使用`JS`动态生成。如经典的管理页面,`HTML`代码只包含分区结构布局代码,菜单项等都由`JS`请求数据动态渲染。 + 2、 `数据`: 异常请求才需要的状态码等冗余数据在正常请求中应去除,只保留数据即可。 + 3、`JS`: 工程化的代码无论如何精简,都包含特别多的运行功能代码,特别是`VUE`、`REACT`等核心代码无法省略。因此本项目不使用现代框架,只在JS原生上进行实现,也不使用工程化,兼容性上尽可能到`ES2015`。 + 4、`CSS`: 尽可能使用`CSS`变量实现差异化,而不是使用`LESS`或`SASS`的循环函数等功能实现。 + 5、`图片`: 主要是图片图标,拆分成单个图标,使用哪个请求哪个,后期根据情况进行合并组合。不同配色使用`filter`实现,尽可能的缩减类似图标。其它图片,根据情况,小图片进行`BASE64`编码。 + 二、技术栈减负 除了工程化,以及现代框架的使用流量带来的压力外,更重要的是就是技术栈压力,对于初创公司的项目,其实无需那么多技术上的考量,因此本项目就只一个要求,只要会写`JS`就能写业务,无需任何额外要求,技术栈要求降到最低,甚至连`HTML`、`CSS`都不用懂,当然了,对于管理功能是可以几乎实现这个要求,对于一些活动页面等还是需要布局要求的,总之,不使用现代框架和工程化,还是可以实现的。 + 三、跨平台 功能性上比较容易,展示方面尽可能的自适应,本项目只是整体框架中的一部分,还需要配合服务器代码以及客户端代码才能完成最终的跨平台功能。尽可能的设计好对接实现原生交互,还有小程序的兼容,这对初创公司来说已经不太适用了,但也仍然尽可能的减少技术栈的要求。 + 四、语言趋同化 `JAVA`和`JAVASCRIPT`虽然名字很像,但其实没啥关系,不过不同语言的发展确实主键趋同化了,特别是这两个名字有点像的语言,它们的语法本身就是类似的,`JAVA`也渐渐的增加了`泛型`、`Lambda`等,`JAVASCRIPT`也渐渐的增加了`class`、`const`等,特别是有了`NodeJS`的运行环境,再加上`TS`,两种语言的开发者兼容起来和方便。本项目一个重要的实现就是关于重载,使得它们更加兼容。因此本项目需要使用到`TS`,不过这仅仅是对于本框架的扩展开发而言。 ## 关于重载 在`TS`的环境下提供了重载的功能,但是,它只是声明,给调用者提供了良好的提示信息,实际上,并没有真正的重载方案。 在`TS`中可以如下声明重载 ```typescript function add(a: number, b: number): number; function add(a: string, b: string): string; ``` 然而`TS`终究是声明,不是运行时,因此,实现重载的代码类似如下 ```typescript function add(a: any, b: any): any { if (typeof a === "number" && typeof b === "number") { return a + b; } else if (typeof a === "string" && typeof b === "string") { return a + b; } } ``` 当重载类型很复杂时,则实现代码将会非常混乱。因此有了参数归一化处理等实现方式,但无论如何,最终实现代码都很难解耦。 本框架提供了一个重载解决方案,配合`TS`使用,将很接近强类型语言的重载,如`JAVA`那样书写代码。 如上例,仍然在`TS`中声明重载(非必须,`TS`只是为了让使用者有更好的提示信息。) ```typescript function add(a: number, b: number): number; function add(a: string, b: string): string; ``` 本框架使用`JS`重载实现方法 ```typescript const add = U.F.overloading('add', { // 对应第一个声明的重载实现 types: [Etype.number, Etype.number], fn: (a: number, b: number) => { return a + b; } }, { // 对应第二个声明的重载实现 types: [Etype.string, Etype.string], fn: (a: string, b: string) => { return a + b; } } ); ``` 即使脱离了`TS`,也并不影响程序的实际执行。 纯`JS`实现如下 ```javascript const add = U.F.overloading('add', { // 对应第一个声明的重载实现 types: [Etype.number, Etype.number], fn: (a, b) => { return a + b; } }, { // 对应第二个声明的重载实现 types: [Etype.string, Etype.string], fn: (a, b) => { return a + b; } } ); ``` 可以看到,本框架的重载方法,对于变量类型的约束,是配置项中的`types`参数决定的,与`TS`无关。 当你调用该方法时 ```javascript add(1, 2) // 3 add("x", "y") // "xy" ``` 而当你调用没有的重载方法时 ```javascript add(1, "y") ``` 控制台将输出错误信息给与提示 ```javascript function[add] is implemented by overloading as follows f(number@number) f(string@string) not implemented by overloading which you call the function as follows f(number@string) f(number@*) f(*@string) f(*@*) f(number@...) f(...) ``` 可以看到,当你调用该重载方法时,框架不但会匹配确定类型,还会在匹配不到精确类型时去匹配可能的适配重载方法,如上例。 ```javascript add(1, "y") // 首先尝试匹配精确类型,即 add(a:number, b:string) // 精确匹配失败时,尝试从最后一个参数开始,进行模糊匹配,直到所有参数都模糊。 // 没有匹配到,则尝试将最后一个参数模糊进行匹配,即 add(a:number, b:any) // 仍然未匹配到,则尝试将前一个参数模糊进行匹配,即 add(a:any, b:string) // 仍然未匹配到,则尝试将所有参数模糊进行匹配,即 add(a:any, b:any) // 模糊匹配依然失败时,则尝试从最后一个参数开始,进行剩余参数匹配,直到全剩余参数。 // 尝试将最后一个参数转成剩余参数匹配,即 add(a:number, ...rest) // 尝试将前一个参数转成剩余参数匹配,即 add(...rest) // 所有可能都尝试过,仍然未匹配到,则报错。 ``` 本框架的重载实现,即满足了`JS`的类型灵活性,又在一定程度上约束了类型实现,且将各个重载实现代码完全解耦。 以下是重载功能的使用示例(`TS`标注只是为了方便明了用途,可以省略。) ```typescript const demo = U.F.overloading('whatever you like', { // 无参 types: [], fn: () => { ... } }, { // 单参 types: [Etype.string], fn: (obj: string) => { ... } }, { // 单参,多种类型,同一实现方法可以合并,在二维数组中定义可能的类型。 types: [[Etype.number, Etype.boolean]], fn: (obj: number | boolean) => { ... } }, { // 多参,与上例不同,多参是一维数组中定义的个数 types: [Etype.number, Etype.boolean], fn: (obj1: number, obj2: boolean) => { ... } }, { // 单参,任意类型 types: [U.F.argType.any], fn: (obj: any) => { ... } }, { // 多参,任意类型 types: [U.F.argType.any, U.F.argType.any], fn: (obj1: any, obj2: any) => { ... } }, { // 多参,混合类型 types: [U.F.argType.any, [Etype.string, Etype.boolean]], fn: (obj1: any, obj2: string | boolean) => { ... } }, { // 剩余参数 types: [U.F.argType.nest], fn: (...objs) => { ... } }, { // 剩余参数 types: [[Etype.string, Etype.boolean], U.F.argType.nest], fn: (obj1: string | boolean, ...objs) => { ... } } ); ``` # 使用 + `tsconfig.json`中已经配置,将所有`ts`文件都合并编译到`./dist/bundle.js`文件中。 + 在项目根目录,运行`tsc`命令执行编译。 ```shell tsc --watch ``` + `tsconfig.prod.json`中已经配置,将所有`ts`文件都合并编译到`./dist/K.js`文件中。 + 在项目根目录,运行`tsc`命令执行编译。 ```shell tsc --watch -p tsconfig.prod.json ``` > 因为未使用工程化,TS命令无法分别编译,因此所有功能代码及测试代码都将被编译到结果文件中,项目通过访问不同的URL地址来区分应该执行哪些测试代码。详见`./test/test.ts` + 访问`./test/index.html`可运行所有测试代码。 + 访问`./plugins/test.html`只运行控件相关测试代码。 + 访问`./core/test.html`可运行核心所有测试代码。 + 访问`./core/DOM/test.html`只运行核心的DOM相关测试代码。 > `plugins`中的测试代码过多,因此,可以通过对应的`.test.ts`中的配置项,修改`test: true`后即可启用。 # 主题 + 通过`HTML`元素的`data-theme`属性配合`CSS`变量实现 + 增加主题样式,需要增加对应的`CSS`文件(`./plugins/theme-${theme}.css`) + 双击`SHIFT`切换主题 + 也可通过调用`K.theme.set()`方法来实现主题切换 # 图标控件 + 图标控件默认使用图标图标 + 图片图标使用`filter`实现,只需提供纯蓝(`#0000ff`)图标,并按照规则书写对应的`CSS`即可。 + `filter`的实现,可以通过`./icons/test/test.html`来匹配。 ## 关于`fontawesome` > `icon`控件兼容了`fontawesome`的使用,但在默认状态下未启用,如需使用`fontawesome`图标,则首先需要在项目中引入`fontawesome`包。 ```shell # 创建的符号链接 mklink /D "${current directory}\fontawesome" "${fontawesome directroy}\fontawesome" ``` > 也可以通过覆盖全局方法`_loadFA_`来自定义实现`fontawesome`的延迟加载行为。 ```javascript // 原代码 let _loadFA_ = () => { _loadFA_ = U.F.fn.void;// 只加载一次 const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = '/fontawesome/css/all.min.css'; document.head.appendChild(link); }; ``` # 代码结构说明 | | | | description | | - | - | - | - | |`/base`|||基础代码目录| ||`BigInt.ts`||低版ES兼容文件,非特殊情况无需实现。| ||`ENV.ts`||`NodeJS`和 浏览器 等 兼容环境的重要实现| ||`Error.ext.ts`||一些常用错误声明文件| ||`TStype.demo.ts`||一些TS常用类型的示例代码| ||`TStype.ts`||TS常用类型声明文件| |`/core`|||核心代码目录| ||`/Array`||数组工具类目录| ||`/DOM`||`DOM`工具类目录| ||`/Function`||函数工具类目录| |||`argType.ts`|用于重载实现的类型| |||`fn.ts`|常用函数实现| |||`overloading.ts`|函数重载实现| |||`Coverloading.ts`|类重载实现| ||`/Number`||数字工具类目录| ||`/Object`||对象工具类目录| ||`/RegExp`||正则工具类目录| ||`/String`||字符串工具类目录| ||`/Utils`||通用工具类目录| |||`typeof.ts`|取类型(在`JS`原生`typeof`基础上,更加细分的类型。)| |||`is.ts`|判断对象是否为指定类型| |||`clone.ts`|深克隆任意类型(支持循环引用)| |||`merge.ts`|深合并任意类型(支持循环引用)| ||`freeze.ts`||工具类冻结,以防篡改。| ||`types.ts`||常用类型声明| ||`values.ts`||常用值声明| |`/data`|||测试数据目录| ||`data-defined`||通过自定义键值取数据| ||`data-standard`||标准格式数据| ||`data-string`||转换成键值数据| |`/dist`|||编译结果目录| ||`bundle.js`||开发环境编译结果| ||`K.js`||生产环境编译结果| |`/icons`|||图片图标目录| ||`/test`||测试图标目录| |||`test.html`|测试图标页面,用于确定`filter`实现。| |||`test.png`|测试图标| ||`${icon}.png`||纯蓝图片图标| |`/plugins`|||控件实现目录| ||`/annotation`||通用注解(装饰器)实现| |||`AC${property}.ts`|用于生成指定属性功能的注解| |||`ACvalue.ts`|用于生成值控件的注解| |||`ACdata.ts`|用于生成数据值控件的注解| ||`/DOM`||`DOM`工具类目录(仅控件可用)| |||`getPlugin.ts`|获取控件对象| |||`getValue.ts`|获取控件值| |||`setValue.ts`|设置控件值| ||`/implements`||具体控件实现目录| |||`${plugin}.ts`|具体控件实现| |||`${plugin}.test.ts`|具体控件测试代码| ||`~~CVP~~.ts`||值控件与数据值控件的超类| ||`~CDVP~.ts`||数据值控件超类| ||`~CP~.ts`||所有控件超类| ||`~CVP~.ts`||值控件超类| ||`color.less`||默认主题配色| ||`plugin.less`||控件样式| ||`theme-${theme}.less`||扩展主题配色| ||`theme.ts`||主题功能实现| |`test`|||仅用于测试的代码目录| ||`assert.ts`||断言| ||`cases.ts`||测试用例| ||`DOM-simulator.ts`||在`NodeJs`环境下模拟`DOM`的实现| ||`test-ENV.ts`||测试环境变量,用于调试代码。| ||`test.ts`||测试代码入口逻辑| |`app.less`|||桌面应用样式| |`favicon.ico`|||站点图标| |`K.png`|||站点`logo`| |`tsconfig.json`|||`TS`项目开发配置文件| |`tsconfig.prod.json`|||`TS`项目生产配置文件|