destroyed?(): void
_updateHandle: Autorun
+ _queueJob: ((fn: () => void) => void)
$forceUpdate: () => void
+ $nextTick: (fn: () => void) => Promise<any>
_self: MountedComponent<D, P> // on proxies only
}
public $options: any
public $proxy: any = null
public $forceUpdate: (() => void) | null = null
+ public $nextTick: ((fn: () => void) => Promise<any>) | null = null
public _rawData: Data | null = null
public _computedGetters: Record<string, ComputedGetter> | null = null
public _destroyed: boolean = false
public _events: { [event: string]: Function[] | null } | null = null
public _updateHandle: Autorun | null = null
+ public _queueJob: ((fn: () => void) => void) | null = null
public _revokeProxy: () => void
public _isVue: boolean = true
import { MountedComponent } from './component'
import { ComponentWatchOptions } from './componentOptions'
-import { autorun, stop, Autorun } from '@vue/observer'
+import { autorun, stop } from '@vue/observer'
export function initializeWatch(
instance: MountedComponent,
}
// TODO deep watch
+// TODO sync watch
export function setupWatcher(
instance: MountedComponent,
keyOrFn: string | Function,
): () => void {
const handles = instance._watchHandles || (instance._watchHandles = new Set())
const proxy = instance.$proxy
+
const rawGetter =
typeof keyOrFn === 'string'
? () => proxy[keyOrFn]
: () => keyOrFn.call(proxy)
+
let oldValue: any
+
+ const applyCb = () => {
+ const newValue = runner()
+ if (newValue !== oldValue) {
+ cb(newValue, oldValue)
+ oldValue = newValue
+ }
+ }
+
const runner = autorun(rawGetter, {
- scheduler: (runner: Autorun) => {
- const newValue = runner()
- if (newValue !== oldValue) {
- cb(newValue, oldValue)
- oldValue = newValue
- }
+ scheduler: () => {
+ // defer watch callback using the scheduler injected defer.
+ instance._queueJob(applyCb)
}
})
+
oldValue = runner()
handles.add(runner)
+
return () => {
stop(runner)
handles.delete(runner)
}
interface RendererOptions {
- queueJob: (fn: () => void, postFlushJob?: () => void) => void
+ scheduler: {
+ nextTick: (fn: () => void) => Promise<any>
+ queueJob: (fn: () => void, postFlushJob?: () => void) => void
+ }
nodeOps: NodeOps
patchData: PatchDataFunction
teardownVNode?: (vnode: VNode) => void
// renderer alongside an actual renderer.
export function createRenderer(options: RendererOptions) {
const {
- queueJob,
+ scheduler: { queueJob, nextTick },
nodeOps: {
createElement: platformCreateElement,
createText: platformCreateText,
(__COMPAT__ && (parentVNode.children as MountedComponent)) ||
createComponentInstance(parentVNode, Component, parentComponent)
+ // renderer-injected scheduler methods
+ instance.$nextTick = nextTick
+ instance._queueJob = queueJob
+
const queueUpdate = (instance.$forceUpdate = () => {
queueJob(instance._updateHandle, flushHooks)
})
import { createRenderer, VNode } from '@vue/core'
-import { queueJob } from '@vue/scheduler'
+import { queueJob, nextTick } from '@vue/scheduler'
import { nodeOps } from './nodeOps'
import { patchData } from './patchData'
import { teardownVNode } from './teardownVNode'
const { render: _render } = createRenderer({
- queueJob,
+ scheduler: {
+ queueJob,
+ nextTick
+ },
nodeOps,
patchData,
teardownVNode
}
}
if (postFlushCb) {
- queuePostFlushCb(postFlushCb)
+ postFlushCbs.push(postFlushCb)
}
if (!flushing) {
nextTick(flushJobs)
}
}
-export function queuePostFlushCb(cb: () => void) {
- postFlushCbs.push(cb)
-}
-
-export function flushJobs() {
+function flushJobs() {
flushing = true
let job
while ((job = queue.shift())) {