Skip to content
This repository has been archived by the owner on Feb 17, 2022. It is now read-only.

Commit

Permalink
Merge pull request #9 from nighca/enhance
Browse files Browse the repository at this point in the history
支持 `watch` & `computed`
  • Loading branch information
nighca authored Sep 19, 2017
2 parents 5b9e8a0 + d6b81d0 commit 22fea79
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 9 deletions.
32 changes: 23 additions & 9 deletions src/install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,25 +11,27 @@ export default function install(Vue: typeof VueClass, mobxMethods: IMobxMethods)

const defineReactive = (Vue as any).util.defineReactive

function beforeCreate(this: VueClass) {
const vm = this
getFromStoreEntries(vm).forEach(({ key, compute }) => {
defineReactive(vm, key, null)
})
}

function created(this: VueClass) {
const vm = this
const fromStore = vm.$options[optionName]
if (!fromStore) {
const entries = getFromStoreEntries(vm)
if (entries.length <= 0) {
return
}

const disposers: Disposer[] = vm[disposersName] = []

Object.keys(fromStore).forEach(key => {
const compute = fromStore[key]
entries.forEach(({ key, compute }) => {
disposers.push(mobxMethods.reaction(
() => compute.apply(vm),
val => {
if (key in vm) {
vm[key] = val
} else {
defineReactive(vm, key, val)
}
vm[key] = val
},
true
))
Expand All @@ -47,7 +49,19 @@ export default function install(Vue: typeof VueClass, mobxMethods: IMobxMethods)
}

Vue.mixin({
beforeCreate,
created,
beforeDestroy
})
}

function getFromStoreEntries(vm: VueClass) {
const fromStore = vm.$options[optionName]
if (!fromStore) {
return []
}

return Object.keys(fromStore).map(
key => ({ key, compute: fromStore[key] })
)
}
58 changes: 58 additions & 0 deletions test/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,64 @@ test(`can use this.data in ${optionName}`, done => {
})
})


test(`fields in ${optionName} can be used in watch & computed`, done => {
Vue.use(Movue, { reaction })

const data = observable({
foo: 1
})

const onFooChange = jest.fn()
const onFoobarChange = jest.fn()

const vm = new Vue({
data() {
return {
bar: 2
}
},
computed: {
foobar() {
return this.foo + this.bar
}
},
[optionName]: {
foo() {
return data.foo
}
},
watch: {
foo(value) {
onFooChange(value)
},
foobar(value) {
onFoobarChange(value)
}
},
render (h) {
const vm: any = this
return h('div', `${vm.foobar}`)
}
}).$mount()

expect(vm.$el.textContent).toBe('3')

vm.bar++
runInAction(() => {
data.foo++
})

nextTick(() => {
expect(vm.$el.textContent).toBe('5')
expect(onFooChange.mock.calls).toHaveLength(1)
expect(onFooChange.mock.calls[0][0]).toBe(2)
expect(onFoobarChange.mock.calls).toHaveLength(1)
expect(onFoobarChange.mock.calls[0][0]).toBe(5)
done()
})
})

class Counter {
@observable num = 0
@computed get numPlus() {
Expand Down

0 comments on commit 22fea79

Please sign in to comment.