Remix 中没有中间件,面对重复的代码应该如何是好?

一、问题

Remix 目前还没有中间件,开发路由时,有些公用的代码需要重复的编写。例如每一个路由 action/loader 都需要判断是否授权。

重复是我们不愿意看到的。

那么有没有办法解决重复的问题?

二、别的框架是如何解决重复问题的?

  • express: 中间件

大部分框架都是使用中间件来解决重复的代码问题。但是明显现在 Remix 还没有中间件支持。

  • 装饰器函数

一个装饰器在写好了,可以在类中各种装饰。但是装饰器也是有限制了的。只能在 class 中使用。

到此我们就引出了我们的正题:

在 Remix 中使用 class static method + 装饰器,解决重复代码大量重复的问题。

三、问题代码

ts 复制代码
export const action: ActionFunction = async ({
  request,
  params,
}: ActionFunctionArgs) => {
  const session = await getSession(request.headers.get("Cookie"));
  const lang = params?.lang || defaultLang;

  const dataDto = await request.json();
  let validateDataDto: TLogin;
   // 登录流程...
};

这是一个简单的 action 处理,如果我们登录,每次进入需要授权的页面都需要先进行授权和认证,显示的调用与正常业务无关的内容。

四、为什么会思考到静态函数?

ts 复制代码
const date = Date.now()

Date 是 JS 内置的一个函数,now 方法就是一个静态方式,说明其实我们隐式写 JS、TS 的时候一直在与静态方法打交道。然后再 TS 装饰器中不能直接修饰函数,而可以修饰静态方式。这样我们就可以使用装饰器,在对静态函数进行修饰了。

五、ts 中的 class + 静态函数

ts 复制代码
function console() {
    console.log("loader call")
}
export class LoginHandler {
    @console
    static loader() {}
     @console
    static action() {}
}

console 的函数用于装饰 loader 在 loader 函数调用之前调用。在我们 Remix 路由中,我们就可以直接导入class类型和静态方法。

ts 复制代码
import {LoginHandler} from '~/LoginHandler'

export const action: ActionFunction = LoginHandler.action
export const loader: ActionFunction = LoginHandler.loader

当然如果有更加项目可能逻辑比这个复杂,下面我们系统的 TS 的装饰器内容。

六、装饰器学习资源

七、在 TS stage 2 下中使用装饰器需要完成以下步骤

注意:虽然装饰器已经到了第三个阶段,但是以下还是

ts.config 配置: 基础配置

ts 复制代码
{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  }
}

如果要支持反射

sh 复制代码
npm i reflect-metadata --save
ts 复制代码
{
  "compilerOptions": {
    "target": "ES5",
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true,
  }
}

八、装饰器分类

  • 类装饰器:应用于类构造函数,可以用来修改类的行为或元数据。
  • 方法装饰器:应用于类的方法,可以修改方法的行为或元数据。
  • 访问符装饰器: 应用于类的放问题,可以修改该访问器的行为和元数据。
  • 属性装饰器:应用于类的属性,可以修改属性的行为或元数据。
  • 参数装饰器:应用于类的构造函数或方法的参数,可以修改参数的行为或元数据。

九、普通装饰器和装饰器工厂

就是一个带有 target 参数的函数:

ts 复制代码
function console(target) {
    // do some things
}

target 就是我们装饰的目标(类,函数,属性,函数参数)

装饰器工厂,其实就是一个典型的 JavaScript 闭包函数:

ts 复制代码
function color(value: string) {
  return function (target) {
    // do something with 'target' and 'value'...
  };
}

很简单:函数和闭包函数,以及它们的参数需要熟悉。

十、方法装饰器

ts 复制代码
function MethodDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log("Method Decorator called on: ", propertyKey);
}
  1. target: 装饰的目标类的原型对象。
  2. propertyKey: 被装饰的方法的名称。
  3. descriptor: 被装饰方法的属性描述符。

场景需求,我们将装饰的目标方法重写

ts 复制代码
function MethodDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log("Method Decorator called on: ", propertyKey);

    const originalMethod = descriptor.value; // 保存原有方法

    // 重写原始方法
    descriptor.value = function(...args: any[]) {
        console.log("Method execution starts");
        const result = originalMethod.apply(this, args); // 调用原始方法
        console.log("Method execution ends");
        return result;
    };

    return descriptor;
}

其实就是简单存储原有方法,然后干一些需要自定义事情,然后再调用原来的方式,返回结果的过程。

十一、多装饰器执行顺序

  • 对于类的装饰器,执行顺序是从类的上方向下执行。
  • 而对于类的方法、属性或参数的装饰器,执行顺序是从左到右执行。

十二、有一个定义良好的顺序的装饰器应该这样做:

ts 复制代码
// 1. 类装饰器
function ClassDecorator(target: any) {
    console.log("Class Decorator");
}

// 2. 方法装饰器
function MethodDecorator(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
    console.log("Method Decorator on: ", propertyKey);
}

// 3. 属性装饰器
function PropertyDecorator(target: any, propertyKey: string) {
    console.log("Property Decorator on: ", propertyKey);
}

// 4. 参数装饰器
function ParameterDecorator(target: any, propertyKey: string, parameterIndex: number) {
    console.log("Parameter Decorator on: ", propertyKey, " with index: ", parameterIndex);
}

@ClassDecorator
class ExampleClass {
    @PropertyDecorator
    exampleProperty: string;

    @MethodDecorator
    exampleMethod(@ParameterDecorator param1: string, @ParameterDecorator param2: number) {
        console.log("Example method called");
    }
}
  1. 类装饰器:放在最上面,因为它们应用于整个类,影响类的构造函数及其行为。
  2. 方法装饰器:在类装饰器之后,因为它们应用于类的方法,可以修改方法的行为或元数据。
  3. 属性装饰器:在方法装饰器之后,因为它们应用于类的属性,可以修改属性的行为或元数据。
  4. 参数装饰器:放置在最后,因为它们应用于类的构造函数或方法的参数,可以修改参数的行为或元数据。

十三、内置装饰器

内置装饰器:TypeScript提供了一些内置的装饰器,例如

  • @deprecated: 表示废弃
  • @sealed: 表示冻结
  • @readonly: 表示只读
  • @experimental:试验性质
  • @abstract:表示抽象方法
  • ...

十四、为什么需要 reflect-metadata

reflect-metadata 提供了一种在 JavaScript 运行时获取 TypeScript 类的装饰器和类型信息的方式,使得开发者能够更灵活地处理类的元数据和类型信息,从而实现一些高级的编程模式和功能。

十五、使用装饰器库的框架和库类

  • class-transformer
  • typeorm
  • Angular
  • NestJS

十六、小结

相关推荐
一條狗20 小时前
隨筆 20241224 ts寫入excel表
开发语言·前端·typescript
轻口味2 天前
配置TypeScript:tsconfig.json详解
ubuntu·typescript·json
小林rr3 天前
前端TypeScript学习day03-TS高级类型
前端·学习·typescript
web150850966413 天前
前端TypeScript学习day01-TS介绍与TS部分常用类型
前端·学习·typescript
前端熊猫3 天前
省略内容在句子中间
前端·javascript·typescript
禁止摆烂_才浅3 天前
React全家桶 -【高阶函数/高阶组件/钩子】-【forwardRef、mome、useImperativeHandle、useLayoutEffect】
react.js·typescript
TSFullStack4 天前
TypeScript - 控制结构
typescript
高山我梦口香糖4 天前
[react] 优雅解决typescript动态获取redux仓库的类型问题
前端·react.js·typescript
乐闻x4 天前
如何使用 TypeScript 和 Jest 编写高质量单元测试
javascript·typescript·单元测试·jest
Web阿成4 天前
1.学习TypeScript 类型
javascript·typescript