{"id":24099913,"url":"https://github.com/indios/vue-ts-decorate","last_synced_at":"2025-05-07T22:25:28.350Z","repository":{"id":93719801,"uuid":"72718102","full_name":"InDIOS/vue-ts-decorate","owner":"InDIOS","description":"A set of TypeScript decorators for make the work with Vue.js easiest.","archived":false,"fork":false,"pushed_at":"2017-12-14T13:43:34.000Z","size":140,"stargazers_count":12,"open_issues_count":1,"forks_count":1,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-14T12:55:32.552Z","etag":null,"topics":["decorators","javascript","typescript","vue-components","vuejs"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/InDIOS.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","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":"2016-11-03T07:07:12.000Z","updated_at":"2021-04-29T11:03:12.000Z","dependencies_parsed_at":"2023-03-06T23:00:30.479Z","dependency_job_id":null,"html_url":"https://github.com/InDIOS/vue-ts-decorate","commit_stats":{"total_commits":72,"total_committers":4,"mean_commits":18.0,"dds":"0.13888888888888884","last_synced_commit":"f77a287b5619a7a7024a8c46becea6a2dfb0b830"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InDIOS%2Fvue-ts-decorate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InDIOS%2Fvue-ts-decorate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InDIOS%2Fvue-ts-decorate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/InDIOS%2Fvue-ts-decorate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/InDIOS","download_url":"https://codeload.github.com/InDIOS/vue-ts-decorate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252963431,"owners_count":21832503,"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":["decorators","javascript","typescript","vue-components","vuejs"],"created_at":"2025-01-10T15:56:40.810Z","updated_at":"2025-05-07T22:25:28.338Z","avatar_url":"https://github.com/InDIOS.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# vue-ts-decorate\n\nA set of [TypeScript](http://www.typescriptlang.org/) decorators for make the work with [Vue.js](http://vuejs.org) easiest.\n\n\u003e **Note:** This project take some ideas and examples of the projects [av-ts](https://github.com/HerringtonDarkholme/av-ts), [vue-ts](https://github.com/weichx/vue-ts) and [vue-typescript](https://github.com/itsFrank/vue-typescript).\n\n## The Why?\nThe projects mentioned in the note above are very good but, for some reasons not include some decorators that i believe are important too,\nfurther are incompatible with Vue 2.x.x.\n\n## Features\n\n* Compatibility with Vue version 1.x.x and 2.x.x.\n* **@Component:** Create a Vue component: `Vue.extend` and `Vue.component`.\n  * **@Prop:** Create a component property.\n  * **@On:** Create a component `on` event listener. **--\u003e Work only with Vue 1.x.x**\n  * **@Once:** Create a component `once` event listener. --\u003e **Work only with Vue 1.x.x**\n  * **@Watch:** Create a component watcher.\n  * **@Getter:** Create a component getter from state property. **--\u003e Work only with Vuex \u003e=0.6.3 \u003c0.7.0**\n  * **@Action:** Create a component action. **--\u003e Work only with Vuex \u003e=0.6.3 \u003c0.7.0**\n* **@Directive:** Create a Vue directive, local or global.\n* **@Filter:** Create a Vue filter, local or global.\n* **@Mixin:** Create a mixin object.\n\n## Use with VueRouter and Vuex 2.x.x\n* VueRouter methods `beforeRouteEnter` and `beforeRouteLeave` are supported as class methods (without decoration).\n* With Vuex, for better usability and performance, use `map*` (* means `State`, `Getters`, `Actions` and `Mutations`) Vuex module methods in component options with the object spread operator. \n\n# Configuration\nFollow the Vue configuration for Webpack and Browserify related in [Vue Doc](https://vuejs.org/v2/guide/installation.html)\n\n## See all the examples below:\n\n## Usage\n\n```\n// class only\n@Component() \n  or\n@Component(options)\n```\n\n### Basic Component declaration\n\n```javascript\nimport * as Vue from 'vue';\nimport { Component } from 'vue-ts-decorate';\n// or use\n// import Component from 'vue-ts-decorate/component';\n\n@Component()\nclass MyComponent extends Vue {\n  // No annotated properties are added to `data` property.\n  someData: string = '';\n\n  // methods named as instance hooks are added like hooks\n  mounted() {\n    this.someData = 'Hello!, MyComponent.';\n  }\n\n  // No annotated methods ara added to `methods` property.\n  someMethod() {\n    // ...\n  }\n}\n\nnew MyComponent().$mount('#app');\n```\nThe code above it is the same that:\n\n\u003eNOTE: All Vue Router hooks are also supported as classes methods, except the `activate` hook because it has the same name as the Vue components hook in the version 1.x.x. In version 2.x.x only `beforeRouteEnter` and `beforeRouteLeave` are added as hooks.\n\n```javascript\nlet MyComponent = Vue.extend({\n  data: {\n    someData: ''\n  },\n  mounted() {\n    this.someData = 'Hello!, MyComponent.';\n  },\n  methods: {\n    someMethod() {\n      // ...\n    }\n  }\n});\n\nnew MyComponent().$mount('#app')\n```\nThe **@Component** decorator receives an object as an optional parameter with the same properties of a Vue component, to these properties is added the `componentTag` property which is a string to specify the name of the tag will have the component. If it is present, the component will be a global, otherwise will be local. `el` property are deprecate. To do a mounted component see below:\n\n### Example\n\n```javascript\n// Mounted Component\n@Component()\nclass MountedComp extends Vue {\n  // ...\n}\nnew MountedComp().$mount('#app');\n\n// Global Component\n@Component({ componentTag: 'globalComp' })\nclass GlobalComp {\n  // ...\n}\n\n// local Component\n@Component()\nclass LocalComp {\n  // ...\n}\n```\n\nThe example above it is the same that:\n\n```javascript\n// Mounted Component\nlet MountedComp = Vue.extend({\n  // ...\n});\nnew MountedComp().$mount('#app');\n\n// Global Component\nVue.component('global-comp', {\n  // ...\n});\n\n// local Component\nVue.extend({\n  name: 'LocalComp'\n  // ...\n});\n```\nYes, in the `componentTag` you can use the camelCase style.\n\nComponents can take other components too, in the options of **@Component**\n\n```javascript\n// Child Component\n@Component()\nclass ChildComp {\n  // ...\n}\n\n// Parent Component\n@Component({ \n  components: { ChildComp }\n})\nclass ParentComp {\n  // ...\n}\n```\n\n## Props, Events and Watchers\n\n```\n// properties or methods only\n@Prop()\n  or\n@Prop(options)\n```\n```\n// methods only\n@On(eventName)\n@Once(eventName)\n```\n```\n// methods only\n@Watch(propertyName)\n  or\n@Watch(propertyName, options)\n```\n\n```javascript\nimport * as Vue from 'vue';\nimport { Component, Prop, Watch, On, Once } from 'vue-ts-decorate';\n\n@Component()\nclass MyComponent extends Vue { // the class extends of Vue just to get intellitSense inside the methods\n  someVar: string = 'Hello!';\n\n  @Prop({\n    // all property options\n  })\n  someProp:string;\n\n  @Prop({\n    type: String\n  })\n  someDefaultProp:string = 'some default value'; \n\n  // vue-ts-decorate makes sure to deep clone default values for array and object types\n  @Prop()\n  someObjProp: { some_default: string } = { some_default: 'value' };\n\n  // defined functions decorated with prop are treated as the default value\n  @Prop()\n  someFuncProp() { \n    // ...\n  }\n\n  someMethod() {\n    // ...\n  }\n\n  // Watch accept a string who would be the property name\n  // and an options object as second parameter\n  @Watch('someVar')\n  someVarWatcher(newVal, oldVal) {\n    // ...\n  }\n\n  @On('eventToEmit') // if param is omited then, the function name is used as a event name\n  someEvent() {\n    // ...\n  }\n\n  @Once('eventToEmitOnce') // if param is omited then, the function name is used as a event name\n  someEventOnce() {\n    // ...\n  }\n}\n```\n\nIt is equivalent to\n\n```javascript\nVue.extend({\n  name: 'MyComponent',\n  data() {\n    return {\n      someVar: 'Hello!'\n    };\n  },\n  props: {\n    someProp: null,\n    someDefaultProp: {\n      type: String,\n      default: 'some default value'\n    },\n    someObjProp: {\n      default() {\n        return { \n          some_default: 'value' \n        };\n      }\n    },\n    someFuncProp: {\n      type: Function,\n      default() {\n        // ...\n      }\n    }\n  },\n  methods: {\n    someMethod() {\n      // ...\n    }\n  },\n  watchs: {\n    someVar(newVal, oldVal) {\n      // ...\n    }\n  },\n  events: {\n    eventToEmit() {\n      // ...\n    },\n    eventToEmitOnce() {\n      // ...\n    }\n  }\n});\n```\n\n## Support for Vuex 1.x.x\n\n\u003e NOTE: In version 2.x.x this decorators fail silent. Please see the Vuex 2 documentation for how to use the `maps` methods.\n```javascript\nimport { someAction } from '../actions';\nimport { Component, Getter, Action } from 'vue-ts-decorate';\n\n@Component()\nclass MyComponent {\n  // Getter accept a string with the properties of the state\n  // in the format: 'foo.bar.baz'.\n  // NOTE: Omit the `state` in the string because it is added internaly.\n  @Getter('app.counter')\n  counter:string;\n\n  // or just put the function as a parameter of the Getter.\n  @Getter((state) =\u003e state.app.hello + ' World')\n  someProp:string; \n\n  // Action accept a function as parameter.\n  // NOTE: I use a property with type `(params) =\u003e void` to tell the compiler that\n  // the property is a function and get intellitSense;\n  @Action(someAction)\n  someFuncProp: (someParam) =\u003e void;\n\n  // ...\n}\n```\nThe equivalent in javascript is\n\n```javascript\nVue.extend({\n  name: 'MyComponent',\n  vuex: {\n    getters: {\n      someProp(state) {\n        return state.app.counter;\n      }\n    },\n    actions: {\n      someFuncProp: someAction\n    }\n  }\n  // ...\n});\n```\n\n## Directive\n\n```javascript\nimport { Component, Directive, VueDirective } from 'vue-ts-decorate';\n\n// The property `name` in directive's option is required to make a safe uglification.\n// This is a global directive.\n// The methods `bind` and `unbind` are optionals\n// just the `update` method is required.\n// NOTE: To get intellitSense and fix possible errors inside the methods,\n// the directive class must be extends of `VueDirective` abstract class\n@Directive({ name: 'myGlobalDirective', /* other directive options */ })\nclass MyGlobalDirective extends VueDirective {\n  bind() {\n    // ...\n  }\n\n  update() {\n    // ...\n  }\n\n  unbind() {\n    // ...\n  }\n}\n\n// With the `local` boolean property\n// you can declare a local directive.\n// NOTE: Directives classes just with `update` method\n// are converted to functions, otherwise will be an object.\n@Directive({ name: 'myLocalDirective', local: true, /* other directive options */ })\nclass MyLocalDirective extends VueDirective {\n  update() {\n    // ...\n  }\n}\n\n// and in the component\n@Component({ \n  /* other options */,\n  // the name of the directives \n  // is converte in kebab-case internaly as well\n  directives: { MyLocalDirective }\n})\nclass MyComponent {\n  // ...\n}\n```\n\nThe equivalent in javascript\n\n```javascript\nVue.directive('my-global-directive', {\n  // options go here\n  bind: function() {\n    // ...\n  },\n  update: function() {\n    // ...\n  },\n  unbind: function() {\n    // ...\n  }\n});\n\nVue.extend({\n  // options go here\n  directives: {\n    'my-local-directive': function() {\n      // ...\n    }\n  }\n});\n\n\n```\n\n## Filters\n\n### @Filter decorator receives two parameters: \n\nThe first is required and is the name of the filter, and the second is a boolean that indicate if the filter is global or not.\n\n```javascript\nimport { Component, Filter } from 'vue-ts-decorate';\n\n// This is a global filter.\n// The filter class just need a method called `filter`\n@Filter('myGlobalFilter')\nclass MyGlobalFilter {\n  filter(value: any, ...params: any[]) {\n    // ...\n  }\n}\n\n// This is a local filter.\n@Filter('myLocalFilter', true)\nclass MyLocalFilter {\n  filter(value: any, ...params: any[]) {\n    // ...\n  }\n}\n\n// and in the component\n@Component({ \n  /* other options */\n  filters: { MyLocalFilter }\n})\nclass MyComponent {\n  // ...\n}\n\n// This is a tow way binding filter.\n@Filter('myTowWayFilter')\nclass MyTowWayFilter {\n  read(value: any) {\n    // ...\n  }\n\n  write(value: any, ...params: any[]) {\n    // ...\n  }\n}\n```\n\nand in javascript\n\n```javascript\nVue.filter('myGlobalFilter', function(value, params) {\n  // ...\n});\n\nVue.extend({\n\tname: 'MyComponent',\n  filters: {\n    myLocalFilter: function(value, params){\n      // ...\n    }\n  }\n  // and other options...\n});\n\nVue.filter('myTowWayFilter', {\n  read: function(value) {\n\t\t// ...\n\t},\n  write: function(value, params) {\n\t\t// ...\n\t}\n});\n```\n\n## Mixins\n\n```javascript\nimport { Component, Mixin } from 'vue-ts-decorate';\n\n// Global Mixins are availables with the the\n// `global` property set to true, otherwise \n// (can be omited) mixin is local.\n@Mixin({ global: true })\nclass GlobalMixin {\n  someGlobalProp: string = 'some value';\n\n  someGlobalMethod() {\n    // ...\n  }\n}\n\n// Mixins are classes with the same behavior\n// of components but are not converted in one.\n@Mixin()\nclass ParentMixin {\n  someProp: string = 'some value';\n\n  someMethod() {\n    // ...\n  }\n}\n\n// All decorators and options are the same as components.\n@Mixin({ /* options go here */ })\nclass ChildMixin extends ParentMixin { // Mixins can extends of other Mixins.\n  someChildProp: string = 'some value';\n\n  someChildMethod() {\n    // ...\n  }\n}\n\n@Mixin()\nclass BrotherMixin extends ParentMixin {\n  someBrotherProp: string = 'some value';\n\n  someBrotherMethod() {\n    // ...\n  }\n}\n\n// To simulate the multiple inheritance,\n// we can do like describe the TypeScript Mixins Docs,\n// to get intellitSense and fix possible errors.\n// https://github.com/Microsoft/TypeScript-Handbook/blob/master/pages/Mixins.md\n@Component({ mixins: [BrotherMixin] })\nclass MyComponent extends ChildMixin implements BrotherMixin {\n\n  someBrotherProp: string;\n  someBrotherMethod: () =\u003e void;\n  // ...\n\n}\n```\n\nin javascript\n\n```javascript\nVue.mixin({\n  data: function() {\n    return { \n      someGlobalProp: 'some value' \n    };\n  },\n  methods: {\n    someGlobalMethod: function() {\n      // ...\n    }\n  }\n});\n\nvar ChildMixin = {\n  data: {\n    someProp:'some value',\n    someChildProp: 'some value'\n  },\n  methods: {\n    someMethod: function() {\n      // ...\n    },\n    someChildMethod: function() {\n      // ...\n    }\n  }\n}\n\nvar BrotherMixin = {\n  data: {\n    someProp:'some value',\n    someBrotherProp: 'some value'\n  },\n  methods: {\n    someMethod: function() {\n      // ...\n    },\n    someBrotherMethod: function() {\n      // ...\n    }\n  }\n}\n\nVue.extend({ \n  // ...\n  mixins: [ChildMixin, BrotherMixin] \n});\n```\n\u003e Note on using new with component classes:\n\nYou can call a class with the `new` operator only if `componentTag` property is not set or present in the @Component decorator options. \n\n# TO-DO\n- Add examples.\n- Make more tests.\n- Document how use style property for scoped style and how it works.\n\n# Contributions\n\nAny contribution are accepted if going in the good way and, of course, feel free to  report an issues too, if something going bad.\n\n# License\n\n[MIT](http://opensource.org/licenses/MIT)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Findios%2Fvue-ts-decorate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Findios%2Fvue-ts-decorate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Findios%2Fvue-ts-decorate/lists"}