@gowiny/vue-class
v1.1.5
Published
Vue 3 用类的形式编写组件,面向对象(OOP)编程,并提供了常用的装饰器,可以自定义装饰器
Downloads
82
Maintainers
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
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">
的情况
<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">
两个标签共用的情况
<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
来修改默认实现
支持的装饰器
@Options
@Prop
@State
@Action
@Mutation
@Getter
@Provide
@Inject
@Watch
@Prop
export default class App extends Vue {
@Prop
declare readonly title:string
}
等同于
export default defineComponent( {
name: 'App',
props:['title']
})
export default class App extends Vue {
@Prop({
default:'hello gowiny!'
})
declare readonly title:string
}
等同于
export default defineComponent( {
name: 'App',
props:{
title:{
default:'hello gowiny!'
}
}
})
@State
export default class App extends Vue {
@State
declare readonly appName:string
}
等同于
export default defineComponent( {
name: 'App',
computed:{
appName(){
this.$store.state.appName
}
}
})
export default class App extends Vue {
@State("app.version")
declare readonly appVersion:string
}
等同于
export default defineComponent( {
name: 'App',
computed:{
appVersion(){
this.$store.state.app.version
}
}
})
@Action
export default class App extends Vue {
@Action
saveScreenSize!:(screenSize:any)=>Promise<any>
}
等同于
export default defineComponent( {
name: 'App',
methods:{
saveScreenSize(screenSize:any):Promise<any>{
return this.$store.dispatch("saveScreenSize",screenSize)
}
}
})
export default class App extends Vue {
@Action("app/saveScreenSize")
saveScreenSize!:(screenSize:any)=>Promise<any>
}
等同于
export default defineComponent( {
name: 'App',
methods:{
saveScreenSize(screenSize:any):Promise<any>{
return this.$store.dispatch("app/saveScreenSize",screenSize)
}
}
})
@Inject
export default class App extends Vue {
@Inject
getScreenSize!:()=>any
}
等同于
export default defineComponent( {
name: 'App',
inject: ['getScreenSize']
})
export default class App extends Vue {
@Inject
getScreenSize(){
return {width:800,height:600}
}
}
等同于
export default defineComponent( {
name: 'App',
inject: {'getScreenSize':{
default:function(){
return {width:800,height:600}
}
}}
})
export default class App extends Vue {
@Inject("screenWidth")
width:number
}
等同于
export default defineComponent( {
name: 'App',
inject:{
width:{
from:'screenWidth'
}
}
})
export default class App extends Vue {
@Inject({from:'screenWidth',default:800})
width!:number
}
等同于
export default defineComponent( {
name: 'App',
inject: {
width:{
from:'screenWidth',
default:800
}
}
})
#其他装饰器的用法都类似,不再一一举例