refactor: layout optional features

This commit is contained in:
Evan You
2018-09-25 17:55:47 -04:00
parent 7484b4d2e6
commit b12247d638
6 changed files with 13 additions and 12 deletions

View File

View File

@@ -0,0 +1,57 @@
import { observable } from '@vue/observer'
import { Component } from '../component'
import { Slots } from '../vdom'
const contextStore = observable() as Record<string, any>
export class Provide extends Component {
updateValue() {
contextStore[this.$props.id] = this.$props.value
}
created() {
if (__DEV__) {
if (contextStore.hasOwnProperty(this.$props.id)) {
console.warn(
`A context provider with id ${this.$props.id} already exists.`
)
}
this.$watch(
() => this.$props.id,
(id: string, oldId: string) => {
console.warn(
`Context provider id change detected (from "${oldId}" to "${id}"). ` +
`This is not supported and should be avoided.`
)
},
{ sync: true }
)
}
this.updateValue()
}
beforeUpdate() {
this.updateValue()
}
render(_: any, slots: Slots) {
return slots.default && slots.default()
}
}
if (__DEV__) {
Provide.options = {
props: {
id: {
type: String,
required: true
},
value: {
required: true
}
}
}
}
export class Inject extends Component {
render(props: any, slots: Slots) {
return slots.default && slots.default(contextStore[props.id])
}
}

View File

@@ -0,0 +1,58 @@
import { VNode } from '../vdom'
import { MountedComponent } from '../component'
export interface DirectiveBinding {
instance: MountedComponent
value?: any
arg?: string
modifiers?: DirectiveModifiers
}
export type DirectiveHook = (
el: any,
binding: DirectiveBinding,
vnode: VNode,
prevVNode: VNode | void
) => void
export interface Directive {
beforeMount: DirectiveHook
mounted: DirectiveHook
beforeUpdate: DirectiveHook
updated: DirectiveHook
beforeUnmount: DirectiveHook
unmounted: DirectiveHook
}
type DirectiveModifiers = Record<string, boolean>
export function applyDirective(
vnode: VNode,
directive: Directive,
instance: MountedComponent,
value?: any,
arg?: string,
modifiers?: DirectiveModifiers
): VNode {
const data = vnode.data || (vnode.data = {})
for (const key in directive) {
const hook = directive[key as keyof Directive]
const hookKey = `vnode` + key[0].toUpperCase() + key.slice(1)
const vnodeHook = (vnode: VNode, prevVNode?: VNode) => {
hook(
vnode.el,
{
instance,
value,
arg,
modifiers
},
vnode,
prevVNode
)
}
const existing = data[hookKey]
data[hookKey] = existing ? [].concat(existing, vnodeHook as any) : vnodeHook
}
return vnode
}

View File