Skip to content

Commit 9f55493

Browse files
committed
vmodel,test,docs
1 parent 51d44e0 commit 9f55493

18 files changed

+387
-3
lines changed

docs/_sidebar.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
- [Property](class-component/property/property.md)
66
- [Method](class-component/method/method.md)
77
- [Lifecycle hooks](class-component/lifecycle-hook/lifecycle-hook.md)
8+
- [Component property](class-component/component-property/component-property.md)
89
- [Getter](class-component/getter/getter.md)
910
- [Event](class-component/event/event.md)
1011
- [Reference](class-component/reference/reference.md)
1112
- [Watcher](class-component/watcher/watcher.md)
1213
- [Injection](class-component/injection/injection.md)
14+
- [VModel](class-component/v-model/v-model.md)
1315
- Inheritance
1416
- [ECMAScript class](inheritance/es-class/es-class.md)
1517
- [Component](inheritance/component/component.md)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
import { Prop, Component, Vue } from 'vue-facing-decorator'
3+
4+
/*
5+
6+
Vue option component
7+
{
8+
props:{
9+
p:{
10+
default: 'foo'
11+
}
12+
}
13+
}
14+
*/
15+
16+
@Component
17+
export default class MyComponent extends Vue {
18+
@Prop({
19+
default: 'foo'
20+
})
21+
p!: string
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
import { Prop, Component, Vue } from 'vue-facing-decorator'
3+
4+
/*
5+
6+
Vue option component
7+
{
8+
props:{
9+
p:{
10+
required:true
11+
}
12+
}
13+
}
14+
*/
15+
16+
@Component
17+
export default class MyComponent extends Vue {
18+
@Prop({
19+
required: true
20+
})
21+
p!: string
22+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
import { Prop, Component, Vue } from 'vue-facing-decorator'
3+
4+
/*
5+
6+
Vue option component
7+
{
8+
props:{
9+
p:{
10+
type: String
11+
}
12+
}
13+
}
14+
*/
15+
16+
@Component
17+
export default class MyComponent extends Vue {
18+
@Prop({
19+
type: String
20+
})
21+
p!: string
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
2+
import { Prop, Component, Vue } from 'vue-facing-decorator'
3+
4+
/*
5+
6+
Vue option component
7+
{
8+
props:{
9+
p:{
10+
validator(val:any){
11+
return true
12+
}
13+
}
14+
}
15+
}
16+
*/
17+
18+
@Component
19+
export default class MyComponent extends Vue {
20+
@Prop({
21+
validator(val:any){
22+
return true
23+
}
24+
})
25+
p!: string
26+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
import { Prop, Component, Vue } from 'vue-facing-decorator'
3+
4+
/*
5+
6+
Vue option component
7+
{
8+
props:{
9+
p:{
10+
11+
}
12+
}
13+
}
14+
*/
15+
16+
@Component
17+
export default class MyComponent extends Vue {
18+
@Prop
19+
p!: string
20+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## Usage
2+
3+
Use `Prop` decorator to define a watcher in vue's `props`.
4+
5+
[](./code-usage.ts ':include :type=code typescript')
6+
7+
## Options
8+
9+
### default
10+
11+
This is the `default` in vue `props`.
12+
13+
[](./code-option-default.ts ':include :type=code typescript')
14+
15+
### required
16+
17+
This is the `required` in vue `props`.
18+
19+
[](./code-option-required.ts ':include :type=code typescript')
20+
21+
### type
22+
23+
This is the `type` in vue `props`.
24+
25+
[](./code-option-type.ts ':include :type=code typescript')
26+
27+
### validator
28+
29+
This is the `validator` in vue `props`.
30+
31+
[](./code-option-validator.ts ':include :type=code typescript')
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { VModel, Component, Vue } from 'vue-facing-decorator'
2+
3+
/*
4+
5+
Vue option component
6+
{
7+
props:{
8+
value:{}
9+
},
10+
computed:{
11+
valueAgent:{
12+
get(){
13+
return this['value']
14+
},
15+
set(value){
16+
this.$emit('update:value',value)
17+
}
18+
}
19+
}
20+
}
21+
*/
22+
23+
/*
24+
In other components:
25+
<MyComponent v-model:value="foo"></MyComponent>
26+
*/
27+
28+
@Component
29+
export default class MyComponent extends Vue {
30+
@VModel({
31+
name: 'value'
32+
})
33+
valueAgent!: string
34+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import { VModel, Component, Vue } from 'vue-facing-decorator'
2+
3+
/*
4+
5+
Vue option component
6+
{
7+
props:{
8+
modelValue:{
9+
type:String,
10+
default:'bar',
11+
//...
12+
}
13+
},
14+
computed:{
15+
valueAgent:{
16+
get(){
17+
return this['modelValue']
18+
},
19+
set(value){
20+
this.$emit('update:modelValue',value)
21+
}
22+
}
23+
}
24+
}
25+
26+
*/
27+
28+
/*
29+
30+
In other components:
31+
32+
<MyComponent v-model="foo"></MyComponent>
33+
34+
*/
35+
36+
@Component
37+
export default class MyComponent extends Vue {
38+
@VModel({
39+
type: String,
40+
default: 'bar',
41+
//...
42+
})
43+
valueAgent!: string
44+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { VModel, Component, Vue } from 'vue-facing-decorator'
2+
3+
/*
4+
5+
Vue option component
6+
{
7+
props:{
8+
modelValue:{}
9+
},
10+
computed:{
11+
valueAgent:{
12+
get(){
13+
return this['modelValue']
14+
},
15+
set(value){
16+
this.$emit('update:modelValue',value)
17+
}
18+
}
19+
}
20+
}
21+
22+
*/
23+
24+
/*
25+
26+
In other components:
27+
28+
<MyComponent v-model="foo"></MyComponent>
29+
30+
*/
31+
32+
@Component
33+
export default class MyComponent extends Vue {
34+
@VModel
35+
valueAgent!: string
36+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## Usage
2+
3+
Use `VModel` decorator to define a model for vue `v-model` or `v-model:foo`.
4+
5+
[](./code-usage.ts ':include :type=code typescript')
6+
7+
## Options
8+
9+
### name
10+
11+
The name of `v-model` property, default is `modelValue`.
12+
13+
[](./code-option-name.ts ':include :type=code typescript')
14+
15+
### Same options in `Prop` decorator.
16+
17+
The other options are same as in `Prop` decorator.
18+
19+
[](./code-option-others.ts ':include :type=code typescript')
20+

src/component.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { build as optionWatch, WatchConfig } from './option/watch'
88
import { build as optionProps, PropsConfig } from './option/props'
99
import { build as optionInject, InjectConfig } from './option/inject'
1010
import { build as optionEmit } from './option/emit'
11+
import { build as optionVModel, VModelConfig } from './option/vmodel'
1112
export interface OptionBuilder {
1213
name?: string
1314
data?: Record<string, any>
@@ -17,11 +18,13 @@ export interface OptionBuilder {
1718
watch?: Record<string, WatchConfig>
1819
props?: Record<string, PropsConfig>
1920
inject?: Record<string, InjectConfig>
21+
beforeCreateCallbacks?:Function[]
2022

2123
}
2224
export interface Cons { new(): any, prototype: any }
2325
function ComponentOption(cons: Cons, extend?: any) {
2426
const optionBuilder: OptionBuilder = {}
27+
optionVModel(cons,optionBuilder)
2528
optionComputed(cons, optionBuilder)
2629
optionWatch(cons, optionBuilder)
2730
optionProps(cons, optionBuilder)

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ export { decorator as Watch } from './option/watch'
55
export { decorator as Prop } from './option/props'
66
export { decorator as Inject } from './option/inject'
77
export { decorator as Emit } from './option/emit'
8-
8+
export { decorator as VModel } from './option/vmodel'
99
import type {
1010
ComponentPublicInstance,
1111
ComponentOptions

src/option/methodsAndLifecycle.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ export function build(cons: Cons, optionBuilder: OptionBuilder) {
5050
})
5151

5252
Object.assign(optionBuilder.methods, MethodFunctions)
53+
const bccbs = optionBuilder.beforeCreateCallbacks
54+
if (bccbs && bccbs.length > 0) {
55+
const oldBc = LifecycleFunctions['beforeCreate']
56+
LifecycleFunctions['beforeCreate']=function(){
57+
bccbs.forEach(bccb=>bccb.apply(this,arguments))
58+
if(oldBc){
59+
oldBc.apply(this,arguments)
60+
}
61+
}
62+
}
5363
Object.assign(optionBuilder.lifecycle, LifecycleFunctions)
5464

5565
}

src/option/ref.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,4 @@ export function build(cons: Cons, optionBuilder: OptionBuilder) {
1919
}
2020
})
2121
}
22-
23-
2422
}

src/option/vmodel.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { Cons, OptionBuilder } from '../component'
2+
import { obtainSlot, optoinNullableMemberDecorator } from '../utils'
3+
import { decorator as PropsDecorator, PropsConfig } from './props'
4+
export type VModelConfig = PropsConfig & {
5+
name?: string
6+
}
7+
export const decorator = optoinNullableMemberDecorator(function (proto: any, name: string, option?: VModelConfig) {
8+
option ??= {}
9+
const slot = obtainSlot(proto)
10+
let vmodelName = 'modelValue'
11+
const propsConfig = { ...option }
12+
if (propsConfig) {
13+
vmodelName = propsConfig.name ?? vmodelName
14+
delete propsConfig.name
15+
}
16+
PropsDecorator(propsConfig)(proto, vmodelName)
17+
let map = slot.obtainMap<Map<string, VModelConfig>>('v-model')
18+
map.set(name, option)
19+
})
20+
21+
22+
export function build(cons: Cons, optionBuilder: OptionBuilder) {
23+
optionBuilder.computed ??= {}
24+
const slot = obtainSlot(cons.prototype)
25+
const names = slot.obtainMap<Map<string, VModelConfig>>('v-model')!
26+
if (names && names.size > 0) {
27+
names.forEach((value, name) => {
28+
let vmodelName = (value && value.name) ?? 'modelValue'
29+
optionBuilder.computed![name] = {
30+
get: function (this: any) {
31+
return this[vmodelName]
32+
},
33+
set: function (val: any) {
34+
this.$emit(`update:${vmodelName}`, val)
35+
}
36+
}
37+
})
38+
}
39+
}

0 commit comments

Comments
 (0)