{"id":18825013,"url":"https://github.com/lulusir/clean-js","last_synced_at":"2025-04-14T01:31:21.151Z","repository":{"id":58942260,"uuid":"456465832","full_name":"lulusir/clean-js","owner":"lulusir","description":"一个包含状态库、IOC容器的辅助库，帮助你在在react和vue中管理状态，  简单， 轻量， 方便测试；","archived":false,"fork":false,"pushed_at":"2023-03-10T09:26:36.000Z","size":3778,"stargazers_count":26,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-27T15:48:54.912Z","etag":null,"topics":["clean-architecture","dependency-injection","ioc-container","presenter","react","state-management","typescript","vue"],"latest_commit_sha":null,"homepage":"https://lulusir.github.io/clean-js","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lulusir.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-02-07T10:52:17.000Z","updated_at":"2024-09-25T08:02:10.000Z","dependencies_parsed_at":"2023-01-31T18:16:25.725Z","dependency_job_id":null,"html_url":"https://github.com/lulusir/clean-js","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lulusir%2Fclean-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lulusir%2Fclean-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lulusir%2Fclean-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lulusir%2Fclean-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lulusir","download_url":"https://codeload.github.com/lulusir/clean-js/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248807541,"owners_count":21164703,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clean-architecture","dependency-injection","ioc-container","presenter","react","state-management","typescript","vue"],"created_at":"2024-11-08T00:58:10.647Z","updated_at":"2025-04-14T01:31:19.801Z","avatar_url":"https://github.com/lulusir.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align = \"center\"\u003e@clean-js/presenter\u003c/h1\u003e\n\n\u003cdiv align=\"center\"\u003e\n\n![NPM version](https://img.shields.io/npm/v/@clean-js/presenter.svg?style=flat)\n![Gzip size](https://img.badgesize.io/https:/unpkg.com/@clean-js/presenter/dist/index.js?label=gzip%20size\u0026compression=gzip)\n![GitHub](https://img.shields.io/npm/l/@clean-js/presenter)\n\n\u003c/div\u003e\n\n[Docs](https://lulusir.github.io/clean-js/)\n\n\n\n\u003ch2 align = \"center\"\u003e 目的\u003c/h2\u003e\n\n为了进一步实现整洁架构，使用 mvp 的方式组织你的前端代码，让项目更加清晰\n\n\u003cimg src=\"https://lulusir.github.io/clean-js/mvp.png\" width = \"600\"  alt=\"mvp\" align=center /\u003e\n\n- ViewState，一般是要在界面上显示需要的数据，或者临时数据\n\n- View，一般是 react，vue 之类的视图层，它显示数据，并将事件绑定到 Presenter\n\n- Presenter, 提供方法和 ViewState 给到 View\n- service 实现业务逻辑, 为Presenter提供服务\n\n# 快速上手\n\n## install\n\n```\nnpm install @clean-js/presenter @clean-js/react-presenter --save\n```\n\nor\n\n```\nyarn add @clean-js/presenter @clean-js/react-presenter\n```\n\n\n## Presenter\n\n```typescript\nimport { Presenter, injectable } from '@clean-js/presenter';\n\ninterface IViewState {\n  loading: boolean;\n  name: string;\n}\n\n@injectable()\nexport class NamePresenter extends Presenter\u003cIViewState\u003e {\n  constructor() {\n    super();\n    this.state = {\n      loading: false,\n      name: 'lujs',\n    };\n  }\n\n  changeName() {\n    this.setState((s) =\u003e {\n      s.name += '!';\n    });\n  }\n}\n```\n\n## View\n\n```typescript | pure\nimport React from 'react';\n\nimport { usePresenter } from '@clean-js/react-presenter';\nimport { NamePresenter } from './presenter';\n\nconst Name = () =\u003e {\n  const { presenter, state } = usePresenter(NamePresenter);\n  return (\n    \u003cdiv\u003e\n      \u003cp\u003ename: {state.name}\u003c/p\u003e\n      \u003cbutton\n        onClick={() =\u003e {\n          presenter.changeName();\n        }}\n      \u003e\n        hi\n      \u003c/button\u003e\n    \u003c/div\u003e\n  );\n};\n\nexport default Name;\n```\n\n## tsconfig.json\n\n设置 tsconfig.json\n\n```json\n{\n  \"compilerOptions\": {\n    \"experimentalDecorators\": true,\n    \"emitDecoratorMetadata\": true\n  }\n}\n```\n### 在umi4中使用\n需要在.umirc中添加插件“babel-plugin-transform-typescript-metadata”\n```\nimport { defineConfig } from 'umi';\n\nexport default defineConfig({\n  npmClient: 'pnpm',\n  extraBabelPlugins: ['babel-plugin-transform-typescript-metadata'],\n});\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flulusir%2Fclean-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flulusir%2Fclean-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flulusir%2Fclean-js/lists"}