refactor: depend on scheduler directly in core instead of injecting via createRenderer

This commit is contained in:
Evan You 2018-09-21 13:34:00 -04:00
parent bb0e15de4d
commit de76daf073
11 changed files with 63 additions and 26 deletions

28
.vscode/settings.json vendored
View File

@ -1,3 +1,29 @@
{ {
"typescript.tsdk": "node_modules/typescript/lib" "typescript.tsdk": "node_modules/typescript/lib",
"cSpell.enabledLanguageIds": [
"asciidoc",
"c",
"cpp",
"csharp",
"css",
"go",
"handlebars",
"html",
"jade",
"javascriptreact",
"json",
"latex",
"less",
"markdown",
"php",
"plaintext",
"pub",
"python",
"restructuredtext",
"rust",
"scss",
"text",
"typescriptreact",
"yml"
]
} }

View File

@ -20,6 +20,7 @@
}, },
"homepage": "https://github.com/vuejs/vue/tree/dev/packages/core#readme", "homepage": "https://github.com/vuejs/vue/tree/dev/packages/core#readme",
"dependencies": { "dependencies": {
"@vue/observer": "3.0.0-alpha.1" "@vue/observer": "3.0.0-alpha.1",
"@vue/scheduler": "3.0.0-alpha.1"
} }
} }

View File

@ -8,6 +8,7 @@ import {
} from './componentOptions' } from './componentOptions'
import { setupWatcher } from './componentWatch' import { setupWatcher } from './componentWatch'
import { Autorun, DebuggerEvent, ComputedGetter } from '@vue/observer' import { Autorun, DebuggerEvent, ComputedGetter } from '@vue/observer'
import { nextTick } from '@vue/scheduler'
type Flatten<T> = { [K in keyof T]: T[K] } type Flatten<T> = { [K in keyof T]: T[K] }
@ -70,7 +71,6 @@ export class Component {
public $options: any public $options: any
public $proxy: any = null public $proxy: any = null
public $forceUpdate: (() => void) | null = null public $forceUpdate: (() => void) | null = null
public $nextTick: ((fn: () => void) => Promise<any>) | null = null
public _rawData: Data | null = null public _rawData: Data | null = null
public _computedGetters: Record<string, ComputedGetter> | null = null public _computedGetters: Record<string, ComputedGetter> | null = null
@ -91,6 +91,10 @@ export class Component {
} }
} }
$nextTick(fn: () => any): Promise<any> {
return nextTick(fn)
}
$watch( $watch(
this: MountedComponent, this: MountedComponent,
keyOrFn: string | (() => any), keyOrFn: string | (() => any),

View File

@ -1,6 +1,7 @@
import { MountedComponent } from './component' import { MountedComponent } from './component'
import { ComponentWatchOptions } from './componentOptions' import { ComponentWatchOptions } from './componentOptions'
import { autorun, stop } from '@vue/observer' import { autorun, stop } from '@vue/observer'
import { queueJob } from '@vue/scheduler'
export function initializeWatch( export function initializeWatch(
instance: MountedComponent, instance: MountedComponent,
@ -40,8 +41,9 @@ export function setupWatcher(
const runner = autorun(rawGetter, { const runner = autorun(rawGetter, {
scheduler: () => { scheduler: () => {
// defer watch callback using the scheduler injected defer. // defer watch callback using the scheduler so that multiple mutations
instance._queueJob(applyCb) // result in one call only.
queueJob(applyCb)
} }
}) })

View File

@ -1,4 +1,5 @@
import { autorun, stop } from '@vue/observer' import { autorun, stop } from '@vue/observer'
import { queueJob } from '@vue/scheduler'
import { VNodeFlags, ChildrenFlags } from './flags' import { VNodeFlags, ChildrenFlags } from './flags'
import { EMPTY_OBJ, isReservedProp } from './utils' import { EMPTY_OBJ, isReservedProp } from './utils'
import { import {
@ -56,10 +57,6 @@ interface PatchDataFunction {
} }
interface RendererOptions { interface RendererOptions {
scheduler: {
nextTick: (fn: () => void) => Promise<any>
queueJob: (fn: () => void, postFlushJob?: () => void) => void
}
nodeOps: NodeOps nodeOps: NodeOps
patchData: PatchDataFunction patchData: PatchDataFunction
teardownVNode?: (vnode: VNode) => void teardownVNode?: (vnode: VNode) => void
@ -71,7 +68,6 @@ interface RendererOptions {
// renderer alongside an actual renderer. // renderer alongside an actual renderer.
export function createRenderer(options: RendererOptions) { export function createRenderer(options: RendererOptions) {
const { const {
scheduler: { queueJob, nextTick },
nodeOps: { nodeOps: {
createElement: platformCreateElement, createElement: platformCreateElement,
createText: platformCreateText, createText: platformCreateText,
@ -1189,10 +1185,6 @@ export function createRenderer(options: RendererOptions) {
(__COMPAT__ && (parentVNode.children as MountedComponent)) || (__COMPAT__ && (parentVNode.children as MountedComponent)) ||
createComponentInstance(parentVNode, Component, parentComponent) createComponentInstance(parentVNode, Component, parentComponent)
// renderer-injected scheduler methods
instance.$nextTick = nextTick
instance._queueJob = queueJob
const queueUpdate = (instance.$forceUpdate = () => { const queueUpdate = (instance.$forceUpdate = () => {
queueJob(instance._updateHandle, flushHooks) queueJob(instance._updateHandle, flushHooks)
}) })
@ -1318,6 +1310,9 @@ export function createRenderer(options: RendererOptions) {
} }
} }
flushHooks() flushHooks()
return vnode && vnode.flags & VNodeFlags.COMPONENT_STATEFUL
? (vnode.children as MountedComponent).$proxy
: null
} }
return { render } return { render }

View File

@ -10,6 +10,9 @@ export const Component = InternalComponent as ComponentClass
// observer api // observer api
export * from '@vue/observer' export * from '@vue/observer'
// scheduler api
export { nextTick } from '@vue/scheduler'
// internal api // internal api
export { createComponentInstance } from './componentUtils' export { createComponentInstance } from './componentUtils'

View File

@ -11,3 +11,8 @@ The implementation of this module is inspired by the following prior art in the
- [Meteor Tracker](https://docs.meteor.com/api/tracker.html) - [Meteor Tracker](https://docs.meteor.com/api/tracker.html)
- [nx-js/observer-util](https://github.com/nx-js/observer-util) - [nx-js/observer-util](https://github.com/nx-js/observer-util)
- [salesforce/observable-membrane](https://github.com/salesforce/observable-membrane) - [salesforce/observable-membrane](https://github.com/salesforce/observable-membrane)
## Caveats
- Built-in objects are not observed except for `Map`, `WeakMap`, `Set` and `WeakSet`.

View File

@ -235,5 +235,15 @@ describe('observer/collections', () => {
observed.get('key').a = 2 observed.get('key').a = 2
expect(dummy).toBe(2) expect(dummy).toBe(2)
}) })
it('should observe iterated values (forEach)', () => {})
it('should observe iterated values (values)', () => {})
it('should observe iterated values (keys)', () => {})
it('should observe iterated values (entries)', () => {})
it('should observe iterated values (for...of)', () => {})
}) })
}) })

View File

@ -158,6 +158,7 @@ const immutableInstrumentations: any = {
const target = unwrap(this) const target = unwrap(this)
const proto: any = Reflect.getPrototypeOf(target) const proto: any = Reflect.getPrototypeOf(target)
track(target, OperationTypes.ITERATE) track(target, OperationTypes.ITERATE)
// TODO values retrived from iterations should also be observables
return proto[method].apply(target, args) return proto[method].apply(target, args)
} }
}) })

View File

@ -25,7 +25,6 @@
}, },
"homepage": "https://github.com/vuejs/vue/tree/dev/packages/renderer-dom#readme", "homepage": "https://github.com/vuejs/vue/tree/dev/packages/renderer-dom#readme",
"dependencies": { "dependencies": {
"@vue/core": "3.0.0-alpha.1", "@vue/core": "3.0.0-alpha.1"
"@vue/scheduler": "3.0.0-alpha.1"
} }
} }

View File

@ -1,15 +1,9 @@
import { createRenderer, VNode } from '@vue/core' import { createRenderer, VNode } from '@vue/core'
import { queueJob, nextTick } from '@vue/scheduler'
import { nodeOps } from './nodeOps' import { nodeOps } from './nodeOps'
import { patchData } from './patchData' import { patchData } from './patchData'
import { teardownVNode } from './teardownVNode' import { teardownVNode } from './teardownVNode'
const { render: _render } = createRenderer({ const { render: _render } = createRenderer({
scheduler: {
queueJob,
nextTick
},
nodeOps, nodeOps,
patchData, patchData,
teardownVNode teardownVNode
@ -18,9 +12,6 @@ const { render: _render } = createRenderer({
type publicRender = (node: VNode | null, container: HTMLElement) => void type publicRender = (node: VNode | null, container: HTMLElement) => void
export const render = _render as publicRender export const render = _render as publicRender
// nextTick from scheduler
export { nextTick } from '@vue/scheduler'
// re-export everything from core // re-export everything from core
// h, Component, observer API, flags & types // h, Component, observer API, nextTick, flags & types
export * from '@vue/core' export * from '@vue/core'