فهرست منبع

support keep-alive

Evan You 10 سال پیش
والد
کامیت
a5a9dc9b69

+ 2 - 0
flow/vnode.js

@@ -13,6 +13,7 @@ declare interface MountedComponentVNode {
   componentOptions: VNodeComponentOptions;
   child: Component;
   parent: VNode;
+  data: VNodeData;
 }
 
 // interface for vnodes in update modules
@@ -52,6 +53,7 @@ declare interface VNodeData {
     staticRenderFns: Array<Function>
   };
   directives?: Array<VNodeDirective>;
+  keepAlive?: boolean;
 }
 
 declare type VNodeDirective = {

+ 8 - 0
src/compiler/codegen.js

@@ -72,6 +72,8 @@ function genElement (el: ASTElement): string {
         code = `_m(${staticRenderFns.length - 1})`
       }
     }
+    // check keep-alive
+    code = checkKeepAlive(el, code)
     // platform modules
     for (let i = 0; i < platformModules.length; i++) {
       const transform = platformModules[i].transformElement
@@ -268,6 +270,12 @@ function genComponent (el: ASTElement): string {
   })`
 }
 
+function checkKeepAlive (el: ASTElement, code: string): string {
+  return el.keepAlive
+    ? `_h(_e("vKeepAlive"),function(){return [${code}]})`
+    : code
+}
+
 function genProps (props: Array<{ name: string, value: string }>): string {
   let res = ''
   for (let i = 0; i < props.length; i++) {

+ 3 - 1
src/core/config.js

@@ -77,7 +77,9 @@ const config: Config = {
     'beforeUpdate',
     'updated',
     'beforeDestroy',
-    'destroyed'
+    'destroyed',
+    'activated',
+    'deactivated'
   ],
 
   /**

+ 1 - 1
src/core/instance/lifecycle.js

@@ -54,10 +54,10 @@ export function lifecycleMixin (Vue: Class<Component>) {
       vm._update(vm._render(), hydrating)
     }, noop)
     hydrating = false
-    vm._isMounted = true
     // root instance, call mounted on self
     // mounted is called for child components in its inserted hook
     if (vm.$root === vm) {
+      vm._isMounted = true
       callHook(vm, 'mounted')
     }
     return vm

+ 16 - 4
src/core/vdom/create-component.js

@@ -97,8 +97,10 @@ export function createComponentInstanceForVnode (
 }
 
 function init (vnode: VNodeWithData, hydrating: boolean) {
-  const child = vnode.child = createComponentInstanceForVnode(vnode)
-  child.$mount(hydrating ? vnode.elm : undefined, hydrating)
+  if (!vnode.child) {
+    const child = vnode.child = createComponentInstanceForVnode(vnode)
+    child.$mount(hydrating ? vnode.elm : undefined, hydrating)
+  }
 }
 
 function prepatch (
@@ -116,11 +118,21 @@ function prepatch (
 }
 
 function insert (vnode: MountedComponentVNode) {
-  callHook(vnode.child, 'mounted')
+  if (!vnode.child._isMounted) {
+    vnode.child._isMounted = true
+    callHook(vnode.child, 'mounted')
+  }
+  if (vnode.data.keepAlive) {
+    callHook(vnode.child, 'activated')
+  }
 }
 
 function destroy (vnode: MountedComponentVNode) {
-  vnode.child.$destroy()
+  if (!vnode.data.keepAlive) {
+    vnode.child.$destroy()
+  } else {
+    callHook(vnode.child, 'deactivated')
+  }
 }
 
 function resolveAsyncComponent (

+ 1 - 1
src/platforms/web/compiler/modules/transition.js

@@ -26,7 +26,7 @@ function genData (el: ASTElement): string {
 
 function transformElement (el: ASTElement, code: string): string {
   return el.transitionMode
-    ? `_h(_e('transition-control',{props:{mode:${
+    ? `_h(_e('vTransitionControl',{props:{mode:${
         el.transitionMode
       }}}),function(){return [${code}]})`
     : code

+ 4 - 2
src/platforms/web/runtime/components/index.js

@@ -1,5 +1,7 @@
-import transitionControl from './transition-control'
+import vKeepAlive from './keep-alive'
+import vTransitionControl from './transition-control'
 
 export default {
-  transitionControl
+  vKeepAlive,
+  vTransitionControl
 }

+ 22 - 0
src/platforms/web/runtime/components/keep-alive.js

@@ -0,0 +1,22 @@
+export default {
+  created () {
+    this.cache = Object.create(null)
+  },
+  render () {
+    const childNode = this.$slots.default[0]
+    const cid = childNode.componentOptions.Ctor.cid
+    if (this.cache[cid]) {
+      const child = childNode.child = this.cache[cid].child
+      childNode.elm = this.$el = child.$el
+    } else {
+      this.cache[cid] = childNode
+    }
+    childNode.data.keepAlive = true
+    return childNode
+  },
+  beforeDestroy () {
+    for (const key in this.cache) {
+      this.cache[key].child.$destroy()
+    }
+  }
+}