浏览代码

Revert "refactor(directives): remove binding.instance"

This reverts commit 52cc7e823148289b3dcdcb6b521984ab815fce79.
Evan You 6 年之前
父节点
当前提交
23701666cb
共有 2 个文件被更改,包括 27 次插入2 次删除
  1. 16 0
      packages/runtime-core/__tests__/directives.spec.ts
  2. 11 2
      packages/runtime-core/src/directives.ts

+ 16 - 0
packages/runtime-core/__tests__/directives.spec.ts

@@ -9,6 +9,7 @@ import {
   DirectiveBinding,
   nextTick
 } from '@vue/runtime-test'
+import { currentInstance, ComponentInternalInstance } from '../src/component'
 
 describe('directives', () => {
   it('should work', async () => {
@@ -17,6 +18,7 @@ describe('directives', () => {
     function assertBindings(binding: DirectiveBinding) {
       expect(binding.value).toBe(count.value)
       expect(binding.arg).toBe('foo')
+      expect(binding.instance).toBe(_instance && _instance.proxy)
       expect(binding.modifiers && binding.modifiers.ok).toBe(true)
     }
 
@@ -105,9 +107,13 @@ describe('directives', () => {
       unmounted
     }
 
+    let _instance: ComponentInternalInstance | null = null
     let _vnode: VNode | null = null
     let _prevVnode: VNode | null = null
     const Comp = {
+      setup() {
+        _instance = currentInstance
+      },
       render() {
         _prevVnode = _vnode
         _vnode = withDirectives(h('div', count.value), [
@@ -147,6 +153,7 @@ describe('directives', () => {
     function assertBindings(binding: DirectiveBinding) {
       expect(binding.value).toBe(count.value)
       expect(binding.arg).toBe('foo')
+      expect(binding.instance).toBe(_instance && _instance.proxy)
       expect(binding.modifiers && binding.modifiers.ok).toBe(true)
     }
 
@@ -160,9 +167,13 @@ describe('directives', () => {
       expect(prevVNode).toBe(_prevVnode)
     }) as DirectiveHook)
 
+    let _instance: ComponentInternalInstance | null = null
     let _vnode: VNode | null = null
     let _prevVnode: VNode | null = null
     const Comp = {
+      setup() {
+        _instance = currentInstance
+      },
       render() {
         _prevVnode = _vnode
         _vnode = withDirectives(h('div', count.value), [
@@ -196,6 +207,7 @@ describe('directives', () => {
     function assertBindings(binding: DirectiveBinding) {
       expect(binding.value).toBe(count.value)
       expect(binding.arg).toBe('foo')
+      expect(binding.instance).toBe(_instance && _instance.proxy)
       expect(binding.modifiers && binding.modifiers.ok).toBe(true)
     }
 
@@ -284,6 +296,7 @@ describe('directives', () => {
       unmounted
     }
 
+    let _instance: ComponentInternalInstance | null = null
     let _vnode: VNode | null = null
     let _prevVnode: VNode | null = null
 
@@ -294,6 +307,9 @@ describe('directives', () => {
     }
 
     const Comp = {
+      setup() {
+        _instance = currentInstance
+      },
       render() {
         return withDirectives(h(Child, { count: count.value }), [
           [

+ 11 - 2
packages/runtime-core/src/directives.ts

@@ -15,9 +15,12 @@ import { VNode } from './vnode'
 import { isFunction, EMPTY_OBJ, makeMap, EMPTY_ARR } from '@vue/shared'
 import { warn } from './warning'
 import { ComponentInternalInstance } from './component'
+import { currentRenderingInstance } from './componentRenderUtils'
 import { callWithAsyncErrorHandling, ErrorCodes } from './errorHandling'
+import { ComponentPublicInstance } from './componentProxy'
 
 export interface DirectiveBinding {
+  instance: ComponentPublicInstance | null
   value: any
   oldValue: any
   arg?: string
@@ -105,9 +108,14 @@ export function withDirectives<T extends VNode>(
   vnode: T,
   directives: DirectiveArguments
 ): T {
+  const internalInstance = currentRenderingInstance
+  if (internalInstance === null) {
+    __DEV__ && warn(`withDirectives can only be used inside render functions.`)
+    return vnode
+  }
+  const instance = internalInstance.proxy
   const props = vnode.props || (vnode.props = {})
-  const bindings: DirectiveBinding[] =
-    vnode.dirs || (vnode.dirs = new Array(directives.length))
+  const bindings = vnode.dirs || (vnode.dirs = new Array(directives.length))
   const injected: Record<string, true> = {}
   for (let i = 0; i < directives.length; i++) {
     let [dir, value, arg, modifiers = EMPTY_OBJ] = directives[i]
@@ -119,6 +127,7 @@ export function withDirectives<T extends VNode>(
     }
     bindings[i] = {
       dir,
+      instance,
       value,
       oldValue: void 0,
       arg,