🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis
Socket
Book a DemoInstallSign in
Socket

mtor

Package Overview
Dependencies
Maintainers
1
Versions
35
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

mtor

react 模块化 依赖注入 数据流处理

latest
npmnpm
Version
2.1.15
Version published
Maintainers
1
Created
Source

MTOR 使用文档

目录

  • MTOR简介
  • 安装
  • 基本使用
  • 核心概念
  • 高级特性
  • API参考
  • 最佳实践
  • 常见问题
  • 版本迁移

1. MTOR简介

MTOR是一个基于React的响应式数据流状态管理库,它基于原生React Hooks进行了二次封装,提供了更加简洁、高效的状态管理方案。

1.1 核心特点

MTOR具有以下四大特点:

  • 面向对象:将功能模块中的所有方法、属性和数据封装成一个模型类,由MTOR自动初始化并管理类实例。
  • 依赖注入:参考了Java Spring框架的DI(依赖注入)概念,所有模块类都是单实例的,由框架创建并维护,模块之间可以相互依赖。
  • 异步操作:对异步方法做了大量开发体验方面的优化,异步操作之间的数据修改可以实时反馈到页面中。
  • 其他优势
    • 通用性强,兼容Taro、React Native等React生态
    • 模块跟随页面加载自动注册,无需单独写注入逻辑
    • 热更新数据不丢失,包括类属性和静态属性

1.2 与React Hooks对比

问题React HooksMTOR
属性保存与修改一个useState只能管理一个属性使用setData方法可以同时对多个属性进行修改
可读性随着组件规模增大,展示与业务逻辑混在一起,可读性降低UI展示与业务逻辑分离,结构更清晰,可读性更好
复用性组件里面的业务逻辑不可复用整个模块都是可复用的
数据共享必须使用useContext或属性传值,增加大量非业务代码使用依赖注入,多模块轻松实现共享/内部通信
开发体验热更新时所有state丢失,useMemo、useCallback等依赖项容易出错热更新数据保留,不用关心依赖项更新问题

2. 安装

# 使用npm安装
npm install --save mtor

# 或使用yarn安装
yarn add mtor

3. 基本使用

3.1 简单示例

以下是一个简单的示例,实现从后端获取随机数并在页面中展示,点击按钮可以给随机数加1:

3.1.1 定义模块类

// HomeModel.js
import { service, Model } from 'mtor';

function ajax() { // 模拟ajax请求
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve(parseInt(Math.random() * 10, 10));
        }, 16.7);
    });
}

@service('home') // 或使用 @service(module.id) 或 @define(module)
class HomeModel extends Model {
    num = 0;

    async init() {
        this.num = await ajax();
    }

    add() { // 普通方法
        this.num++;
    }
}

export default HomeModel;

3.1.2 在页面中使用模块

// HomePage.jsx
import React, { useEffect } from 'react';
import { useModel } from 'mtor';
import HomeModel from './HomeModel';

export default () => {
    const model = useModel(HomeModel);
    const { num } = model;
    
    useEffect(() => {
        model.init();
    }, []);
    
    return (
        <div>
            <div onClick={model.add}>+1</div>
            <div>{num}</div>
        </div>
    );
};

3.1.3 使用useInitModel简化代码

// HomePage.jsx
import React from 'react';
import { useInitModel } from 'mtor';
import HomeModel from './HomeModel';

export default () => {
    const model = useInitModel(HomeModel, (m) => m.init(), true);
    const { num } = model;
    
    return (
        <div>
            <div onClick={model.add}>+1</div>
            <div>{num}</div>
        </div>
    );
};

4. 核心概念

4.1 模块定义

模块是MTOR的核心概念,通过@service装饰器定义:

@service('moduleName') // 或使用 @service(module.id) 或 @define(module)
class MyModel extends Model {
    // 属性定义
    count = 0;
    
    // 方法定义
    increment() {
        this.count++;
    }
    
    async fetchData() {
        // 异步操作
    }
}

4.2 依赖注入

MTOR支持模块间的依赖注入,使用@inject装饰器:

import UserModel from './UserModel';

@service(module.id)
class HomeModel extends Model {
    // 注入UserModel实例
    @inject(UserModel)
    user;
    
    async init() {
        // 可以直接使用注入的实例
        console.log(this.user.name);
    }
}

也可以使用@resource按名称注入:

@service(module.id)
class HomeModel extends Model {
    // 按名称注入
    @resource('usermodel')
    user;
}

4.3 数据操作

4.3.1 直接修改属性

在模块方法中可以直接修改属性:

@service(module.id)
class CounterModel extends Model {
    count = 0;
    
    increment() {
        this.count++; // 直接修改属性
    }
}

4.3.2 使用setData方法

可以使用setData方法同时修改多个属性:

@service(module.id)
class UserModel extends Model {
    name = '';
    age = 0;
    
    updateUser(name, age) {
        this.setData({
            name,
            age
        });
    }
}

在组件中也可以直接调用setData

const model = useModel(UserModel);

// 在事件处理函数中
const handleClick = () => {
    model.setData({ name: 'John', age: 30 });
};

5. 高级特性

5.1 异步操作处理

MTOR对异步操作做了特别优化,可以在异步方法中直接修改属性:

@service(module.id)
class DataModel extends Model {
    data = null;
    loading = false;
    error = null;
    
    async fetchData() {
        try {
            this.loading = true; // 修改会立即反映到UI
            this.data = await api.getData();
        } catch (err) {
            this.error = err.message;
        } finally {
            this.loading = false;
        }
    }
}

5.2 模块重置

使用reset方法可以将模块状态重置为初始值:

useEffect(() => {
    model.init();
    return model.reset; // 组件卸载时重置模块
}, []);

6. API参考

6.1 装饰器

  • @service(name: string):定义一个模块
  • @inject(ModelClass):按类型注入依赖
  • @resource(name: string):按名称注入依赖

6.2 Model类

基础模型类,提供以下方法:

  • setData(data: Object):批量设置属性
  • reset():重置模块状态
  • onBeforeReset(callback: Function):注册重置前回调

6.3 Hooks

  • useModel(ModelClass):获取模块实例
  • useInitModel(ModelClass, initFn?, clean?):获取模块实例并处理初始化和清理

6.4 其他API

  • define(module):基于webpack模块定义模块
  • getModels():获取所有模型实例
  • evtBus:事件总线实例

7. 最佳实践

7.1 目录组织

推荐的目录结构:

src/
├── models/
│   ├── HomeModel.js
│   └── UserModel.js
├── pages/
│   ├── Home/
│   │   ├── index.js
│   │   └── style.less
│   └── User/
│       ├── components/
│       │   └── UserCard/
│       │       ├── index.js
│       │       └── style.less
│       ├── index.js
│       └── style.less
└── index.js

7.2 模块定义规范

  • 使用@service(module.id)确保模块名称全局唯一
  • 类名与文件名保持一致
  • 继承Model基类
  • 使用TypeScript或JSDoc提供类型信息
  • 添加热更新支持:module.hot?.accept()
  • 不要随意添加未声明的属性
  • 异步方法封装为Promise
  • 一个页面组件对应一个模型

7.3 组件使用规范

  • 使用useInitModel代替useModel+useEffect组合
  • 页面组件中的业务逻辑放入模型中
  • 列表项组件通过属性传值,不直接使用模型

7.4 对象属性修改

修改对象类型属性时,需要更新引用:

// 错误方式
updateObj() {
    this.obj.a = 2; // 不会触发更新
}

// 正确方式
updateObj() {
    this.obj = { ...this.obj, a: 2 };
}

7.5 热更新优化

在模型文件末尾添加:

// webpack
module.hot?.accept();

// vite
import.meta.hot?.accept();

8. 常见问题

8.1 中文输入法兼容性问题

对于可控组件,推荐使用setData方法:

<Input 
    value={name} 
    onChange={({target: {value}}) => model.setData({name: value})}
/>

8.2 属性未更新到UI

可能的原因:

  • 修改了对象属性但没有更新引用
  • 使用了未在类中声明的属性
  • 在构造函数中调用了异步方法

8.3 模块间循环依赖

避免模块间形成循环依赖,可以使用事件总线或共享服务模式解决。

9. 版本迁移

9.1 从1.x迁移到2.x

主要变化:

  • 使用async/await替代generator方法
  • 对TypeScript支持更友好
  • 底层优化,性能更高效
  • 普通异步回调可以直接通过this修改数据

迁移步骤:

  • 将所有generator方法改为async/await
  • 检查并更新依赖注入方式
  • 更新异步操作处理方式

附录:完整示例

模型定义

// UserModel.ts
import { service, Model } from 'mtor';

@service('usermodel')
class UserModel extends Model {
    name = 'Guest';
    isLoggedIn = false;
    
    login(username: string) {
        this.name = username;
        this.isLoggedIn = true;
    }
    
    logout() {
        this.name = 'Guest';
        this.isLoggedIn = false;
    }
}

export default UserModel;

// HomeModel.ts
import { service, Model, inject } from 'mtor';
import UserModel from './UserModel';

@service(module.id)
class HomeModel extends Model {
    count = 0;
    messages = [];
    
    @inject(UserModel)
    user;
    
    async init() {
        this.messages = await this.fetchMessages();
    }
    
    increment() {
        this.count++;
    }
    
    async fetchMessages() {
        // 模拟API调用
        return new Promise(resolve => {
            setTimeout(() => {
                resolve(['Message 1', 'Message 2', 'Message 3']);
            }, 1000);
        });
    }
}

export default HomeModel;

组件使用

// HomePage.tsx
import React from 'react';
import { useInitModel } from 'mtor';
import HomeModel from '../models/HomeModel';

const HomePage: React.FC = () => {
    const model = useInitModel(HomeModel, m => m.init(), true);
    const { count, messages, user } = model;
    
    return (
        <div>
            <h1>Welcome, {user.name}</h1>
            
            <div>
                <h2>Counter: {count}</h2>
                <button onClick={() => model.increment()}>Increment</button>
            </div>
            
            <div>
                <h2>Messages</h2>
                <ul>
                    {messages.map((msg, index) => (
                        <li key={index}>{msg}</li>
                    ))}
                </ul>
            </div>
            
            {user.isLoggedIn ? (
                <button onClick={() => user.logout()}>Logout</button>
            ) : (
                <button onClick={() => user.login('John')}>Login</button>
            )}
        </div>
    );
};

export default HomePage;

更多信息和示例,请访问GitHub仓库

Keywords

react 模块

FAQs

Package last updated on 11 Dec 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts