npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

hydro-vue-orm

v0.0.1

Published

基于vue3 响应式orm库

Downloads

115

Readme

hydro-vue-orm

安装

npm install hydro-vue-orm
# 或
yarn add hydro-vue-orm

什么是 hydro-vue-orm?

hydro-vue-orm 是基于vue3 响应式系统 实现的一套跨组件、跨页面 同步更新数据的方案

下面是一个基本的示例

<script setup>
import { Entity, Repository, Reactive } from 'hydro-vue-orm'

class UserModel {
  id: string
  name: string
  age: number
}

/** 获取用户详情接口 */
const getUserDetail = (userId) => {
  return fetch(`/api/users/${userId}`).then((res) => res.json()).then((data: UserModel) => {
    return Repository(UserModel).insert(data) as Reactive<UserModel>
  })
}

/** 获取用户列表接口 */
const getUserList = () => {
  return fetch('/api/users').then((res) => res.json()).then((data: UserModel[]) => {
    return data.map((item) => {
      return Repository(UserModel).insert(item) as Reactive<UserModel>
    })
  })
}

const user1 = getUserDetail('userId1')
const user2 = getUserDetail('userId2')
const userList = getUserList()

/**
 * 
 * 点击后, userList中所有id= userId1 的姓名 以及 user1 的姓名 会自动更新成 '用户1更新后的姓名'
 * 不需要手动的去修改user1.name ===xxx, userList.forEach((user) => { user.id === userId1 && (user.name = '用户1更新后的姓名') })
 */
const onTapUpdateUserId1Name = () => {
  Repository(UserModel).where({ id: 'userId1' }).update(user => {
    user.name = '用户1更新后的姓名'
  })
}
</script>

<template>
  <div>用户1姓名: {{ user1.name }}</div>
  <div>用户2姓名: {{ user2.name }}</div>
  <div>用户列表: {{ userList.map((item) => item.name) }}</div>
</template>

核心原理

实现原理

当通过 Repository(UserModel).insert(data) 插入数据时,内部会执行以下步骤:

  1. 创建 UserModel 的实例:new UserModel()
  2. 将数据字段通过 Object.assign 附加到实例上
  3. 使用 vue.reactive 将实例转换为响应式对象
  4. 内部保持对该实例的弱引用
  5. 返回响应式对象

当通过 Repository(UserModel).where({ id: 'userId1' }) 进行操作时,框架会:

  1. 查找所有匹配条件的实例引用
  2. 对这些实例执行增删改查操作
  3. 由于使用了弱引用,当页面上的变量失效时,内部引用会自动释放
  4. 无需担心内存泄漏问题

类对象的优势

由于 insert 方法返回的是类的实例,我们可以在类上定义各种方法和属性,方便前端数据处理:

<script setup>
@Entity()
class UserModel {
  id: number
  name: string

  get userInfo() {
    return `用户姓名:${this.name},用户id:${this.id}`
  }
}

const user1 = Repository(UserModel).insert({ id: 1, name: '用户1' })
</script>
<template>
  <div>用户姓名: {{ user1.name }}</div>
  <div>用户信息: {{ user1.userInfo }}</div>
</template>

便捷数据处理

为了快速将接口数据转换为对应的响应式对象,我们提供了 @Entity 装饰器和 defineSchema 函数,简化数据映射过程:

<script setup>
import { Entity, defineSchema } from 'hydro-vue-orm'

@Entity()
class UserModel {
  id: string
  name: string
  age: number
}

const data1 = [{ id: 1 },{ id: 2 }]
// data1转为了[UserModel, UserModel]
defineSchema([UserModel]).transform(data1)

const data2 = { book: user: { id: 1 } }
// data2自动转为了 { book: { user: UserModel } }
defineSchema({ book: { user: UserModel } }).transform(data2)
</script>

装饰器

以下装饰器不会影响直接 new Class() 的行为,只有通过 Repository(UserModel).insert(data) 插入数据时才会生效:

@Entity()

装饰 class,用来配合 defineSchema 进行数据映射

示例代码

import { Entity } from 'hydro-vue-orm';

@Entity()
class UserModel {
  id: string;
  name: string;
  age: number;
}

@get

装饰属性,当读取实例的属性时触发

示例代码

import { Entity, get } from 'hydro-vue-orm';

@Entity()
class UserModel {
  id: string;
  name: string;
  
  @get((value) => `${value} 岁`)
  age: number;
}

// 使用
const user = Repository(UserModel).insert({ id: '1', name: '张三', age: 30 });
console.log(user.age); // 输出: 30 岁

@set

装饰属性,当设置实例的属性时触发

示例代码

import { Entity, set } from 'hydro-vue-orm';

@Entity()
class UserModel {
  id: string;
  
  @set((value) => value || '未命名')
  name: string;
  
  age: number;
}

// 使用
const user = Repository(UserModel).insert({ id: '1', name: '', age: 30 });
console.log(user.name); // 输出: 未命名

@types

装饰属性,基于 set + defineSchema,用来快捷地将属性转换为指定的类型

示例代码

import { Entity, types } from 'hydro-vue-orm';

@Entity()
class UserModel {
  id: string;
  name: string;
}

@Entity()
class PostModel {
  id: string;
  title: string;
  
  @types(UserModel)
  author: UserModel;
  
  @types([UserModel])
  contributors: UserModel[];
}

// 使用
const post = Repository(PostModel).insert({
  id: '1',
  title: '测试文章',
  author: { id: '1', name: '张三' },
  contributors: [
    { id: '1', name: '张三' },
    { id: '2', name: '李四' }
  ]
});

// post.author 和 post.contributors[0] 都是 UserModel 实例
console.log(post.author.name); // 输出: 张三
console.log(post.contributors[0].name); // 输出: 张三

@cacheSync

装饰属性,慎用。在默认情况下,我们推荐使用 where().update() 来实现批量更新。但在某些特殊场景下,当你期望 id 相同时使用同一引用对象,你可以使用 @cacheSync 装饰器。

示例代码

import { Entity, cacheSync } from 'hydro-vue-orm';

@Entity()
class UserModel {
  @cacheSync()
  id: string;
  name: string;
  age: number;
}

// 使用
const user1 = Repository(UserModel).insert({ id: '1', name: '张三', age: 30 });
const user2 = Repository(UserModel).insert({ id: '1', name: '李四', age: 30 });

// user1 和 user2 是同一个实例
console.log(user1 === user2); // 输出: true
console.log(user1.name); // 输出: 李四, 后者覆盖前者

// 修改其中一个,另一个也会自动更新
user1.name = '王五';
console.log(user2.name); // 输出: 王五

Repository 方法

Repository.insert(data)

插入新实例,返回响应式对象

参数

  • data: 要插入的数据对象

返回值

  • 响应式实例对象

示例代码

const user = Repository(UserModel).insert({ id: '1', name: '张三', age: 30 });
console.log(user.name); // 输出: 张三

Repository.where(conditions).update(callback)

更新匹配的实例

参数

  • conditions: 查询条件对象
  • callback: 更新回调函数,接收匹配的实例作为参数

返回值

  • 更新的实例数组

示例代码

// 更新指定条件的实例
Repository(UserModel).where({ id: '1' }).update(user => {
  user.name = '更新后的姓名';
});

// 更新所有实例
Repository(UserModel).where({}).update(user => {
  user.age = user.age + 1;
});

Repository.where(conditions).delete()

删除匹配的实例

参数

  • conditions: 查询条件对象

返回值

  • 删除的实例数组

示例代码

// 删除指定条件的实例
const deletedUsers = Repository(UserModel).where({ id: '1' }).delete();
console.log(deletedUsers.length); // 输出: 1

Repository.where(conditions).find()

查找匹配的所有实例

参数

  • conditions: 查询条件对象

返回值

  • 匹配的实例数组

示例代码

// 查找指定条件的实例
const users = Repository(UserModel).where({ age: 30 }).find();
console.log(users.length); // 输出: 匹配的用户数量

Repository.where(conditions).findOne()

查找匹配的第一个实例

参数

  • conditions: 查询条件对象

返回值

  • 匹配的实例或 undefined

示例代码

// 查找指定条件的第一个实例
const user = Repository(UserModel).where({ id: '1' }).findOne();
console.log(user?.name); // 输出: 找到的用户姓名

Repository.all()

返回所有实例

返回值

  • 所有实例的数组

示例代码

const allUsers = Repository(UserModel).all();
console.log(allUsers.length); // 输出: 所有用户数量

Repository.clear()

清空所有实例

示例代码

Repository(UserModel).clear();
console.log(Repository(UserModel).all().length); // 输出: 0

Repository.emitter

事件发射器,用于监听实例的插入、更新和删除事件

事件

  • insert: 当实例被插入时触发,参数为插入的实例
  • update: 当实例被更新时触发,参数为更新的实例数组
  • delete: 当实例被删除时触发,参数为删除的实例数组

示例代码

const repo = Repository(UserModel);

// 监听插入事件
repo.emitter.on('insert', user => {
  console.log('用户已插入:', user);
});

// 监听更新事件
repo.emitter.on('update', users => {
  console.log('用户已更新:', users);
});

// 监听删除事件
repo.emitter.on('delete', users => {
  console.log('用户已删除:', users);
});

defineSchema

定义数据映射模式,用来将接口数据转换为对应的响应式对象

参数

  • schema: 数据映射模式,可以是单个模型、模型数组或嵌套对象

返回值

  • 包含 transform 方法的对象

方法

  • transform(data): 将数据转换为对应的响应式对象
    • data: 要转换的数据
    • 返回值: 转换后的响应式对象

示例代码

import { Entity, defineSchema } from 'hydro-vue-orm';

@Entity()
class UserModel {
  id: string;
  name: string;
  age: number;
}

// 转换单个对象
const singleSchema = defineSchema(UserModel);
const user = singleSchema.transform({ id: '1', name: '张三', age: 30 });
console.log(user.name); // 输出: 张三

// 转换数组
const arraySchema = defineSchema([UserModel]);
const users = arraySchema.transform([
  { id: '1', name: '张三', age: 30 },
  { id: '2', name: '李四', age: 25 }
]);
console.log(users.length); // 输出: 2

// 转换嵌套对象
const nestedSchema = defineSchema({
  user: UserModel,
  users: [UserModel]
});
const result = nestedSchema.transform({
  user: { id: '1', name: '张三', age: 30 },
  users: [
    { id: '1', name: '张三', age: 30 },
    { id: '2', name: '李四', age: 25 }
  ]
});
console.log(result.user.name); // 输出: 张三
console.log(result.users.length); // 输出: 2

// 转换深层嵌套对象
const deepSchema = defineSchema({
  book: {
    author: UserModel,
    contributors: [UserModel]
  }
});
const deepResult = deepSchema.transform({
  book: {
    author: { id: '1', name: '张三', age: 30 },
    contributors: [
      { id: '1', name: '张三', age: 30 },
      { id: '2', name: '李四', age: 25 }
    ]
  }
});
console.log(deepResult.book.author.name); // 输出: 张三
console.log(deepResult.book.contributors.length); // 输出: 2

浏览器兼容性

该库兼容所有支持 ES6+ 特性的现代浏览器。

TypeScript 支持

该库使用 TypeScript 编写,提供完整的类型支持。所有实体、仓库和查询构建器都有正确的类型定义。

许可证

MIT