Skip to content

added support for watch as array and moved all the watch logic to seprate module. #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Feb 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 3 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import {
silentGetLazy,
silentSetLazy,
} from './lazy'
import { getWatchedGetter } from './watch'


const prefix = '_async_computed$'
const DidNotUpdate = typeof Symbol === 'function' ? Symbol('did-not-update') : {}
Expand Down Expand Up @@ -137,11 +139,7 @@ function getterFn (key, fn) {
let getter = fn.get

if (fn.hasOwnProperty('watch')) {
const previousGetter = getter
getter = function getter () {
fn.watch.call(this)
return previousGetter.call(this)
}
getter = getWatchedGetter(fn)
}

if (fn.hasOwnProperty('shouldUpdate')) {
Expand Down
41 changes: 41 additions & 0 deletions src/watch.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
const getGetterWatchedByArray = computedAsyncProperty =>
function getter() {
for (let key of computedAsyncProperty.watch) {
if (typeof key !== 'string') throw new Error('AsyncComputed: watch elemnts must be strings')
// check if nested key is watched
const splittedByDot = key.split('.');
if (splittedByDot.length === 1) {
// if not just access it
this[key]
} else {
// access nested propety
try {
var start = this
for (let part of splittedByDot) {
start = start[part]
}
} catch (error) {
console.error('computedAsyncPlugin: bad path: ', key)
throw error
}
}
}
return computedAsyncProperty.get.call(this)
}

const getGetterWatchedByFunction = computedAsyncProperty =>
function getter() {
computedAsyncProperty.watch.call(this)
return computedAsyncProperty.get.call(this)
}


export function getWatchedGetter(computedAsyncProperty) {
if (typeof computedAsyncProperty.watch === 'function') {
return getGetterWatchedByFunction(computedAsyncProperty)
} else if (Array.isArray(computedAsyncProperty.watch)) {
return getGetterWatchedByArray(computedAsyncProperty)
} else {
throw Error('AsyncComouted: watch should be function or an array')
}
}
129 changes: 129 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -885,3 +885,132 @@ test('Data of component still work as function and got vm', t => {
})
t.equal(vm, _vmContext)
})


test("Watch as a function", t => {
t.plan(4)
let i = 0
const vm = new Vue({
data: {
y: 2,
obj: {
t: 0
}
},
asyncComputed: {
z: {
get () {
return Promise.resolve(i + this.y)
},
watch(){
this.obj.t
}
}
}
})
t.equal(vm.z, null)
Vue.nextTick(() => {
t.equal(vm.z, 2)
i++
vm.obj.t--
Vue.nextTick(() => {
// This tick, Vue registers the change
// in the watcher, and reevaluates
// the getter function
t.equal(vm.z, 2)
Vue.nextTick(() => {
// Now in this tick the promise has
// resolved, and z is 3.
t.equal(vm.z, 3)
})
})
})
})


test("Watchers as array with nested path rerun the computation when a value changes", t => {
t.plan(4)
let i = 0
const vm = new Vue({
data: {
y: 2,
obj: {
t: 0
}
},
asyncComputed: {
z: {
get () {
return Promise.resolve(i + this.y)
},
watch: ['obj.t']
}
}
})
t.equal(vm.z, null)
Vue.nextTick(() => {
t.equal(vm.z, 2)
i++
vm.obj.t--
Vue.nextTick(() => {
// This tick, Vue registers the change
// in the watcher, and reevaluates
// the getter function
t.equal(vm.z, 2)
Vue.nextTick(() => {
// Now in this tick the promise has
// resolved, and z is 3.
t.equal(vm.z, 3)
})
})
})
})

test("Watch as array with more then one value", t => {
t.plan(5)
let i = 0
const vm = new Vue({
data: {
y: 2,
obj: {
t: 0
},
r:0
},
asyncComputed: {
z: {
get () {
return Promise.resolve(i + this.y)
},
watch: ['obj.t', 'r']
}
}
})
t.equal(vm.z, null)
Vue.nextTick(() => {
t.equal(vm.z, 2)
i++
// checking for nested property
vm.obj.t--
Vue.nextTick(() => {
// This tick, Vue registers the change
// in the watcher, and reevaluates
// the getter function
t.equal(vm.z, 2)
Vue.nextTick(() => {
// Now in this tick the promise has
// resolved, and z is 3.
t.equal(vm.z, 3)

i++
// one level and multiple watchers
vm.r--
Vue.nextTick(()=>{
Vue.nextTick(() => {
t.equal(vm.z,4)
})
})
})
})
})
})