# @gowiny/vue-class

> Vue 3 用类的形式编写组件，面向对象(OOP)编程，并提供了常用的装饰器，可以自定义装饰器

Latest version **1.1.5** (published 2024-05-22) · MIT license · 0 weekly downloads

## Install

```sh
npm install @gowiny/vue-class
pnpm add @gowiny/vue-class
yarn add @gowiny/vue-class
bun add @gowiny/vue-class
```

## Health

**Score 30/100 (F)** — status: abandoned.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

Negative: abandoned; low maintenance score.

## Facts

| | |
|---|---|
| Version | 1.1.5 |
| Published | 2024-05-22 |
| First published | 2021-06-02 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 3 |
| Unpacked size | 167.1 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Author | Terry |
| Maintainers | gowiny |
| Keywords | gowiny, uniapp, vue3, Decorators, vue-class, babel, typescript |

## Links

- npm: https://www.npmjs.com/package/@gowiny/vue-class
- Repository: https://gitee.com/gowiny/vue-class
- Issues: https://gitee.com/gowiny/vue-class/issues
- npm.io page: https://npm.io/package/@gowiny/vue-class

## Dependencies (3)

- [vue](https://npm.io/package/vue.md) ^3.2.26
- [@babel/runtime](https://npm.io/package/@babel/runtime.md) ^7.17.8
- [@gowiny/js-utils](https://npm.io/package/@gowiny/js-utils.md) ^1.0.0

## Alternatives

- [@openai/codex-sdk](https://npm.io/package/@openai/codex-sdk.md) — 731.4K weekly downloads
- [babel-plugin-transform-react-jsx](https://npm.io/package/babel-plugin-transform-react-jsx.md) — 565.0K weekly downloads
- [babel-helper-remove-or-void](https://npm.io/package/babel-helper-remove-or-void.md) — 508.5K weekly downloads
- [@pnpm/store-controller-types](https://npm.io/package/@pnpm/store-controller-types.md) — 186.9K weekly downloads
- [react-native-signature-canvas](https://npm.io/package/react-native-signature-canvas.md) — 155.6K weekly downloads

## Recent versions

- 1.1.5 (latest) — 2024-05-22
- 1.1.3 — 2023-01-16
- 1.1.2 — 2023-01-06
- 1.1.1 — 2023-01-06
- 1.1.0 — 2023-01-05
- 1.0.68 — 2023-01-05
- 1.0.67 — 2023-01-05
- 1.0.66 — 2023-01-05
- 1.0.65 — 2023-01-05
- 1.0.64 — 2023-01-04
- 1.0.63 — 2022-03-26
- 1.0.62 — 2022-03-26
- 1.0.61 — 2022-03-26
- 1.0.60 — 2022-03-25
- 1.0.59 — 2022-03-24
- … 51 more at https://npm.io/package/@gowiny/vue-class/versions

## README

# goinwy-vue-class
## 说明
此项目是Vue3 的 TypeScript Class 支持项目，支持普通vue 3 项目和 uniapp + vue3 项目


用类的形式编写组件，面向对象(OOP)编程，并提供了常用的装饰器，还可以自定义装饰器


不依赖 `vue-class-component`项目
觉得它的实现方式，跟正常的Class 的用法不一致，所以直接重写了。

`vue-class-component` 的用法，如果子类也写有生命周期的hook，那实际是所有父类的hook 和 子类的 hook 都会执行一次。

此项目，子类重写父类方法后，如果不显式调用super.xxx 的话，是不会执行父类的hook 的。这跟正常的类的继承、重写保持一致


### 详细使用方法，可以查看演示项目

演示项目地址：https://gitee.com/gowiny/uni-example



## 安装教程

###  安装：
```
npm install @gowiny/vue-class
```
###  初始化

* main.ts

```javascript
import vueClass from '@gowiny/vue-class'
import { createSSRApp } from "vue";
import App from "./App.vue";

export function createApp() {
  const app = createSSRApp(App);

  //如果是 Vue Router 项目，则添加 Vue Router 独有的生命周期钩子

  app.use(vueClass,{
    hooks:['beforeRouteEnter','beforeRouteUpdate','beforeRouteLeave']
  })

  //如果是uniapp 项目，则添加uniapp独有的生命周期钩子
  /*
  app.use(vueClass,{
    hooks:['onInit','onLoad','onShow','onReady','onHide','onUnload','onResize','onPullDownRefresh','onReachBottom','onTabItemTap','onShareAppMessage','onPageScroll','onNavigationBarButtonTap',
  'onBackPress','onNavigationBarSearchInputChanged','onNavigationBarSearchInputConfirmed','onNavigationBarSearchInputClicked','onShareTimeline','onAddToFavorites']
  })
  */


  return {
    app,
  };
}

```


### 使用方法一：
单独使用 `<script lang="ts">` 的情况

```xml
<template>
  <view class="container">
	<view>title:{{title}}></view>
	<view>name:{{name}}></view>
	<MyProfile></MyProfile>
	<view><button @click="test1">test1</button>
	<view><button @click="test2">test2</button>
  </view>
</template>
<script  lang="ts">
import { Action,Provide, getOptionsByClass, State,Vue } from '@gowiny/vue-class'
import MyProfile from '@/component/test/my-profile.vue'

@Options({
  components:{
    MyProfile
  }
})
class TestPage extends MyPage{
  title:string='用户信息'
  @State("user.userInfo")
  readonly userInfo!:any
  @Action("user/logout")
  logout!:()=>any

  @Provide("testInject")
  testInject11111(){
    uni.showModal({
      content:'我是 TestPage 提供的 testInject 方法'
    })
  }

  @Provide("provideValue")
  provideValue133333:string="TestPage provideValue"

  test1(){
  	console.log('test1')
  }

  test2(){
	  console.log('test2')
  }
}
export default TestPage
</script>
```

### 使用方法二：
`<script lang="ts">` 和 `<script setup lang="ts">` 两个标签共用的情况

```xml
<template>
  <view class="container">
	<view>title:{{title}}></view>
	<view>name:{{name}}></view>
	<MyProfile></MyProfile>
	<view><button @click="test1">test1</button>
	<view><button @click="test2">test2</button>
  </view>
</template>
<script setup lang="ts">
import MyProfile from '@/component/test/my-profile.vue'
import { ref } from 'vue'
const title = ref('用户信息')
function test1(){
  console.log('test1')
}
</script>

<script  lang="ts">
import { Action,Provide, getOptionsByClass, State,Vue } from '@gowiny/vue-class'
class TestPage extends MyPage{
  @State("user.userInfo")
  readonly userInfo!:any
  @Action("user/logout")
  logout!:()=>any

  @Provide("testInject")
  testInject11111(){
    uni.showModal({
      content:'我是 TestPage 提供的 testInject 方法'
    })
  }

  @Provide("provideValue")
  provideValue133333:string="TestPage provideValue"

  test2(){
	  console.log('test2')
  }
}
/*
这里展示的是<script lang="ts"> 和 <script setup lang="ts"> 两个标签共用的情况。
最后导出的时候，需要使用 getOptionsByClass 函数转换
*/
export default getOptionsByClass(TestPage)
</script>
```

## 可自定义装饰器

提供灵活的自定义装饰器的方法：`createDecorator`

**具体使用方法，请参考源码中已有的装饰器的定义方式**

`createDecorator`方法里的参数：`ctx : OptionsContext`
可以通过设置 `ctx.dataFactory` 、`ctx.beforeHandle` 、`ctx.afterHandle` 来修改默认实现




## 支持的装饰器
```javascript
@Options
@Prop
@State
@Action
@Mutation
@Getter
@Provide
@Inject
@Watch
```
### @Prop
```javascript
export default class App extends Vue {
	@Prop
	declare readonly title:string
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  props:['title']
})
```
------------
```javascript
export default class App extends Vue {
	@Prop({
		default:'hello gowiny!'
	})
	declare readonly title:string
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  props:{
	  title:{
		default:'hello gowiny!'
	}
  }
})
```
------------
### @State
```javascript
export default class App extends Vue {
	@State
	declare readonly appName:string
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  computed:{
  	appName(){
		this.$store.state.appName
  	}
  }
})
```
------------
```javascript
export default class App extends Vue {
	@State("app.version")
	declare readonly appVersion:string
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  computed:{
  	appVersion(){
		this.$store.state.app.version
  	}
  }
})
```
### @Action
```javascript
export default class App extends Vue {
	@Action
	saveScreenSize!:(screenSize:any)=>Promise<any>
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  methods:{
  	saveScreenSize(screenSize:any):Promise<any>{
		return this.$store.dispatch("saveScreenSize",screenSize)
  	}
  }
})
```
------------
```javascript
export default class App extends Vue {
	@Action("app/saveScreenSize")
	saveScreenSize!:(screenSize:any)=>Promise<any>
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  methods:{
  	saveScreenSize(screenSize:any):Promise<any>{
		return this.$store.dispatch("app/saveScreenSize",screenSize)
  	}
  }
})
```
### @Inject
```javascript
export default class App extends Vue {
	@Inject
	getScreenSize!:()=>any
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  inject: ['getScreenSize']
})
```
------------
```javascript
export default class App extends Vue {
	@Inject
	getScreenSize(){
		return {width:800,height:600}
	}
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  inject: {'getScreenSize':{
	  default:function(){
		  return {width:800,height:600}
	  }
  }}
})
```
------------
```javascript
export default class App extends Vue {
	@Inject("screenWidth")
	width:number
}
```
等同于
```javascript
export default defineComponent( {
  name: 'App',
  inject:{
  	width:{
		from:'screenWidth'
	}
  }
})
```
------------
```javascript
export default class App extends Vue {
	@Inject({from:'screenWidth',default:800})
	width!:number
}
```
等同于
```javascript
export default defineComponent( {
	name: 'App',
	inject: {
		width:{
			from:'screenWidth',
			default:800
		}
	}
})
```
#其他装饰器的用法都类似，不再一一举例

---
_Source: https://npm.io/package/@gowiny/vue-class · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
