{"id":20542187,"url":"https://github.com/weivea/vue3-class-mode-dev","last_synced_at":"2026-06-06T10:31:54.498Z","repository":{"id":83302818,"uuid":"321268693","full_name":"weivea/vue3-class-mode-dev","owner":"weivea","description":"本项目是基于 vue3 以自定义 class的模式来开发的尝试(并非使用vue-class-component)；","archived":false,"fork":false,"pushed_at":"2020-12-14T07:56:28.000Z","size":200,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-16T15:22:06.395Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/weivea.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-12-14T07:35:19.000Z","updated_at":"2020-12-14T07:56:30.000Z","dependencies_parsed_at":null,"dependency_job_id":"5b60f764-c644-485b-ad7e-4a177583d73f","html_url":"https://github.com/weivea/vue3-class-mode-dev","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/weivea%2Fvue3-class-mode-dev","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weivea%2Fvue3-class-mode-dev/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weivea%2Fvue3-class-mode-dev/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/weivea%2Fvue3-class-mode-dev/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/weivea","download_url":"https://codeload.github.com/weivea/vue3-class-mode-dev/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242147061,"owners_count":20079486,"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":[],"created_at":"2024-11-16T01:29:43.578Z","updated_at":"2026-06-06T10:31:54.493Z","avatar_url":"https://github.com/weivea.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue3-class-mode-dev\n\n本项目是基于 vue3 以自定义 class的模式来开发的尝试(并非使用vue-class-component)；\n\n使用typescript + tsx 开发\n感觉不错\n\n## sample\n\n```typescript\nimport { defineComponent, DebuggerEvent, watch } from 'vue';\nimport {\n  Base,\n  Ref,\n  Reactive,\n  Mounted,\n  Updated,\n  RenderTriggered,\n} from './vueClass';\n\nimport { State } from '@/store/index';\nimport { useStore } from 'vuex';\nimport { useRouter, useRoute } from 'vue-router';\n\nconst props = {\n  message: {\n    type: String,\n    default: function() {\n      return 'Default string';\n    },\n  },\n};\n\nexport class Test extends Base\u003ctypeof props\u003e {\n  @Ref\n  private data1 = 2;\n\n  @Reactive\n  private dataObj = {\n    bbcnt: 12,\n  };\n\n  $store = useStore\u003cState\u003e();\n  $router = useRouter();\n  $route = useRoute();\n\n  constructor(...args: any[]) {\n    super(...args);\n    // onMounted(this.handleM1.bind(this));\n    watch(\n      () =\u003e {\n        return this.dataObj.bbcnt;\n      },\n      (newval, oldVal) =\u003e {\n        console.log('bbcnt change', newval);\n      },\n    );\n  }\n\n  clickHander() {\n    console.log('1233');\n    this.data1++;\n  }\n  clickHander2() {\n    console.log('bbcnt');\n    this.dataObj.bbcnt++;\n  }\n\n  @RenderTriggered\n  @Mounted\n  handleM1(e?: DebuggerEvent) {\n    this.handleM2();\n    console.log('handleM1', e);\n  }\n\n  @Updated\n  handleM2() {\n    console.log('handleM2', this.$props.message);\n  }\n\n  handleM3() {\n    console.log('handleM3', this.$props.message);\n  }\n  render() {\n    return (\n      \u003cdiv\u003e\n        213134\u003cdiv\u003e{this.$props.message}\u003c/div\u003e1324134\n        \u003cdiv\u003estore: {this.$store.state.key1}\u003c/div\u003e\n        \u003cdiv onClick={this.clickHander.bind(this)}\u003edata1:{this.data1}\u003c/div\u003e\n        \u003cdiv onClick={this.clickHander2.bind(this)}\u003e\n          dataObj.bbcnt:{this.dataObj.bbcnt}\n        \u003c/div\u003e\n      \u003c/div\u003e\n    );\n  }\n}\n\nconst TestTsx = defineComponent({\n  props,\n  setup(props, ctx) {\n    const r = new Test(props, ctx);\n    return r.render.bind(r);\n  },\n});\n\nexport default TestTsx;\n\n\n```\n\n\n```typescript\n// vueClass.ts\nimport {\n  SetupContext,\n  ExtractPropTypes,\n  reactive,\n  ref,\n  getCurrentInstance,\n  onMounted,\n  onBeforeMount,\n  onBeforeUpdate,\n  onUpdated,\n  onBeforeUnmount,\n  onUnmounted,\n  onErrorCaptured,\n  onRenderTracked,\n  onRenderTriggered,\n} from 'vue';\n\nconst hookMethodKey = Symbol('m');\n\n/**\n *  推导props类型\n */\nexport type InferPropsType\u003cP\u003e = Readonly\u003cExtractPropTypes\u003cP\u003e\u003e;\n\nfunction runBind(\n  fn: any,\n  _this: any,\n  bindFun: (hook: () =\u003e any) =\u003e false | Function | undefined,\n) {\n  if (typeof fn === 'function') {\n    bindFun(fn.bind(_this));\n  }\n}\n\n/**\n * 基类\n */\nexport class Base\u003cP = any\u003e {\n  declare $props: InferPropsType\u003cP\u003e;\n  declare $ctx: SetupContext\u003cRecord\u003cstring, any\u003e\u003e;\n  declare [hookMethodKey]: [\n    keyof this,\n    (hook: () =\u003e any) =\u003e false | Function | undefined,\n  ][];\n  constructor(...args: any[]) {\n    Object.defineProperty(this, '$props', {\n      enumerable: false,\n      configurable: false,\n      get() {\n        return args[0];\n      },\n    });\n    Object.defineProperty(this, '$ctx', {\n      enumerable: false,\n      configurable: false,\n      get() {\n        return args[1];\n      },\n    });\n\n    const hooks = this[hookMethodKey];\n    hooks.forEach(([methodName, bindFun]) =\u003e\n      runBind(this[methodName], this, bindFun),\n    );\n    const v = getCurrentInstance();\n    (v as any).__proto__ = this;\n  }\n}\nBase.prototype[hookMethodKey] = [];\n\n/**ref装饰器\n * @param target\n * @param name\n */\nexport function Ref(target: any, name: string | number | symbol): any {\n  const key = Symbol(name.toString());\n  const descriptor: PropertyDescriptor = {\n    enumerable: true,\n    get() {\n      return (this as any)[key].value;\n    },\n    set(val: any) {\n      const _ref = (this as any)[key];\n      if (_ref) {\n        _ref.value = val;\n      } else {\n        (this as any)[key] = ref(val);\n      }\n    },\n  };\n  return descriptor;\n}\n\n/**reactive装饰器\n * @param target\n * @param name\n */\nexport function Reactive(target: any, name: string | number | symbol): any {\n  const key = Symbol(name.toString());\n  const descriptor: PropertyDescriptor = {\n    enumerable: true,\n    get() {\n      return (this as any)[key];\n    },\n    set(val: any) {\n      (this as any)[key] = reactive(val);\n    },\n  };\n  return descriptor;\n}\n\n/** onBeforeMount装饰器\n * @param target\n * @param propertyKey\n */\nexport function BeforeMount(target: any, propertyKey: keyof any) {\n  target[hookMethodKey].push([propertyKey, onBeforeMount]);\n}\n\n/** onMounnted装饰器\n * @param target\n * @param propertyKey\n */\nexport function Mounted(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onMounted]);\n}\n\n/** onUpdated装饰器\n * @param target\n * @param propertyKey\n */\nexport function Updated(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onUpdated]);\n}\n\n/** onBeforeUpdate 装饰器\n * @param target\n * @param propertyKey\n */\nexport function BeforeUpdate(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onBeforeUpdate]);\n}\n\n/** onBeforeUnmount 装饰器\n * @param target\n * @param propertyKey\n */\nexport function BeforeUnmount(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onBeforeUnmount]);\n}\n/** onUnmounted 装饰器\n * @param target\n * @param propertyKey\n */\nexport function Unmounted(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onUnmounted]);\n}\n/** onErrorCaptured 装饰器\n * @param target\n * @param propertyKey\n */\nexport function ErrorCaptured(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onErrorCaptured]);\n}\n/** onRenderTracked 装饰器\n * @param target\n * @param propertyKey\n */\nexport function RenderTracked(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onRenderTracked]);\n}\n/** onRenderTriggered 装饰器\n * @param target\n * @param propertyKey\n */\nexport function RenderTriggered(target: any, propertyKey: keyof any) {\n  target[hookMethodKey]?.push([propertyKey, onRenderTriggered]);\n}\n\n\n```\n\n## Project setup\n```\nnpm install\n```\n\n### Compiles and hot-reloads for development\n```\nnpm run serve\n```\n\n### Compiles and minifies for production\n```\nnpm run build\n```\n\n### Lints and fixes files\n```\nnpm run lint\n```\n\n### Customize configuration\nSee [Configuration Reference](https://cli.vuejs.org/config/).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweivea%2Fvue3-class-mode-dev","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fweivea%2Fvue3-class-mode-dev","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fweivea%2Fvue3-class-mode-dev/lists"}