Skip to content

Commit 1550875

Browse files
committed
🐛 Bind methods accessed by data
Consider a component like this: ```typescript @component class MyComponent { foo = 'foo' options = { handler = this.method, } method() { return this.foo } } ``` When we call `options.handler()`, we would expect to get back `foo`, but this currently doesn't work, because the methods aren't correctly bound in the data builder function. This change actively binds the functions to the Vue component instance, so that the above example works as expected.
1 parent 95ab564 commit 1550875

File tree

3 files changed

+30
-7
lines changed

3 files changed

+30
-7
lines changed

src/index.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ export const Base = class {
3838
(this as any)[key] = vueInstance[key]
3939
})
4040
}
41+
const methods = optionBuilder.methods
42+
if (methods) {
43+
Object.keys(methods).forEach(key => {
44+
(this as any)[key] = methods[key].bind(vueInstance)
45+
})
46+
}
4147
}
4248
} as VueCons
4349

src/option/data.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import { makeObject, obtainSlot, excludeNames, getValidNames } from '../utils'
44

55
export function build(cons: Cons, optionBuilder: OptionBuilder, vueInstance: any, _propNames?: string[]) {
66
optionBuilder.data ??= {}
7-
const sample = new cons(optionBuilder, vueInstance)
8-
let names = getValidNames(sample, (des) => {
9-
return !!des.enumerable
7+
const sample = new cons(optionBuilder, vueInstance) as any
8+
let names = getValidNames(sample, (des, name) => {
9+
return !!des.enumerable && !optionBuilder.methods?.[name]
1010
})
1111
const slot = obtainSlot(cons.prototype)
1212
names = excludeNames(names, slot)

test/option/data.ts

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,24 @@ import { Component, Base, Prop } from '../../dist'
55
import { mount } from '@vue/test-utils'
66

77
@Component
8-
export class Comp extends Base {
8+
export class DataComp extends Base {
99
data = 'data value'
1010
@Prop
1111
prop!: string
1212
fieldInitProp = this.prop
13+
14+
methods = [this.method];
15+
options = {
16+
handler: this.method,
17+
}
18+
wrapped = () => this.method();
19+
20+
method() {
21+
return this.data
22+
}
1323
}
1424

15-
const CompContext = Comp as any
25+
const CompContext = DataComp as any
1626

1727
describe('option data',
1828
() => {
@@ -25,9 +35,16 @@ describe('option data',
2535

2636
expect('function').to.equal(typeof CompContext?.data)
2737
expect('data value').to.equal(CompContext.data().data)
28-
expect(2).to.equal(Object.keys(CompContext.data()).length)
38+
expect(5).to.equal(Object.keys(CompContext.data()).length)
2939
expect('prop test').to.equal(vm.fieldInitProp)
3040
})
41+
42+
it('binds methods to the component context', () => {
43+
const {vm} = mount(CompContext)
44+
expect('data value').to.equal(vm.methods[0]())
45+
expect('data value').to.equal(vm.options.handler())
46+
expect('data value').to.equal(vm.wrapped())
47+
})
3148
}
3249
)
33-
export default {}
50+
export default {}

0 commit comments

Comments
 (0)