vue3 oop 文档
类组件+自动化的依赖注入(可选) = 极致的代码体验 DEMO
需要reflect-metadata 的支持
pnpm add @abraham/reflection injection-js
项目入口需要引入 reflect-metadata
import '@abraham/reflection'
tsconfig.json
需要增加配置:
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"useDefineForClassFields": false
}
}
pnpm add vue3-oop
因为esbuild不支持装饰器的metadata属性,所以需要安装 @vue3-oop/plugin-vue-jsx
插件使用原始ts编译
import { Autobind, ComponentProps, Computed, Hook, Link, Mut, VueComponent } from 'vue3-oop'
import { Directive, VNodeChild, watch } from 'vue'
interface FooProps {
size: 'small' | 'large'
// 组件的slots
slots: {
item(name: string): VNodeChild
}
}
class Foo extends VueComponent<FooProps> {
// vue需要的运行时属性检查
static defaultProps: ComponentProps<FooProps> = ['size']
constructor() {
super()
// watch在构造函数中初始化
watch(
() => this.count,
() => {
console.log(this.count)
},
)
}
// 组件自身状态
@Mut() count = 1
// 计算属性
@Computed()
get doubleCount() {
return this.count * 2
}
add() {
this.count++
}
// 自动绑定this
@Autobind()
remove() {
this.count--
}
// 生命周期
@Hook('Mounted')
mount() {
console.log('mounted')
}
// 对元素或组件的引用
@Link() element?: HTMLDivElement
render() {
return (
<div ref="element">
<span>{this.props.size}</span>
<button onClick={() => this.add()}>+</button>
<span>{this.count}</span>
<button onClick={this.remove}>-</button>
<div>{this.context.slots.item?.('aaa')}</div>
<input type="text" v-focus/>
</div>
)
}
}
组件和服务的差距是缺少了render这一个表现UI的函数,其他都基本一样
class CountService extends VueService {
@Mut() count = 1
add() {
this.count++
}
remove() {
this.count--
}
}
Angular文档
import { VueComponent, VueService } from 'vue3-oop'
import { Injectable } from 'injection-js'
// 组件DI
@Component({
providers: [CountService]
})
class Bar extends VueComponent {
constructor(private countService: CountService) {super()}
render() {
return <div>{this.countService.count}</div>
}
}
@Injectable()
class BarService extends VueService {
constructor(private countService: CountService) {super()}
}
![](https://private-user-images.githubusercontent.com/11799110/257462883-30a79e6d-6b5a-4213-a863-cee70f83d4c8.jpg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE1ODgzMTYsIm5iZiI6MTcyMTU4ODAxNiwicGF0aCI6Ii8xMTc5OTExMC8yNTc0NjI4ODMtMzBhNzllNmQtNmI1YS00MjEzLWE4NjMtY2VlNzBmODNkNGM4LmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzIxVDE4NTMzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTMzZTU4ZmEwOGI3NDQyYjM3YTRkMWYxOGE4YjJiZWUxYzBkMjRiNTUzYzY5NGMwYzE2OTEzYjE0YTdlMzcwZGEmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.-i5J5hBsh6jKm9GgY2SRYDxAXlQ8-budaOiRiEspfA4)
![](https://private-user-images.githubusercontent.com/11799110/257462887-ea4e359a-0037-4c41-8e80-091547dd0bca.jpg?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjE1ODgzMTYsIm5iZiI6MTcyMTU4ODAxNiwicGF0aCI6Ii8xMTc5OTExMC8yNTc0NjI4ODctZWE0ZTM1OWEtMDAzNy00YzQxLThlODAtMDkxNTQ3ZGQwYmNhLmpwZz9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MjElMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzIxVDE4NTMzNlomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPWQyMjliYjlkNzg5ZjI4MTUyNTlhODAwYWIyZmNlYjI1ZWEyZWZjODVlNDFhYjNiNDc1ZDkwMWY3YjM5OWJlNmImWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.s6oeO3p6kM5rvEG6BbioDNGliGIwGH1pKEJ0WOT_QHY)