Browse Source

ensure abstract HOCs do not alter parent chain

dev
Evan You 9 years ago
parent
commit
cb67ffe442
  1. 1
      flow/component.js
  2. 2
      src/core/components/keep-alive.js
  3. 4
      src/core/instance/lifecycle.js
  4. 17
      src/core/instance/render.js
  5. 2
      src/core/util/env.js
  6. 2
      src/core/vdom/create-element.js
  7. 2
      src/platforms/web/runtime/components/transition-control.js

1
flow/component.js

@ -47,6 +47,7 @@ declare interface Component {
_isVue: true;
_self: Component;
_renderProxy: Component;
_renderParent: ?Component;
_watcher: Watcher;
_watchers: Array<Watcher>;
_data: Object;

2
src/core/components/keep-alive.js

@ -1,4 +1,6 @@
export default {
name: 'keep-alive',
_abstract: true,
created () {
this.cache = Object.create(null)
},

4
src/core/instance/lifecycle.js

@ -10,7 +10,7 @@ export function initLifecycle (vm: Component) {
vm.$parent = options.parent
vm.$root = vm.$parent ? vm.$parent.$root : vm
if (vm.$parent) {
if (vm.$parent && !options._abstract) {
vm.$parent.$children.push(vm)
}
@ -145,7 +145,7 @@ export function lifecycleMixin (Vue: Class<Component>) {
vm._isBeingDestroyed = true
// remove self from parent
const parent = vm.$parent
if (parent && !parent._isBeingDestroyed) {
if (parent && !parent._isBeingDestroyed && !vm.$options._abstract) {
remove(parent.$children, vm)
}
// teardown watchers

17
src/core/instance/render.js

@ -16,7 +16,7 @@ import {
} from '../vdom/create-element'
export const renderState: {
activeInstance: Component | null
activeInstance: ?Component
} = {
activeInstance: null
}
@ -35,6 +35,19 @@ export function initRender (vm: Component) {
) {
return this._h(this._e(tag, data, namespace), children)
}, vm)
// for abstract components, determine first non-abstract parent
// so that the children of abstract components are considered children
// of the first non-abstract parent.
// this is used by internal abstract components like <keep-alive>.
if (vm.$options._abstract) {
let parent = vm.$parent
while (parent && parent.$options._abstract) {
parent = parent.$parent
}
vm._renderParent = parent
} else {
vm._renderParent = vm
}
if (vm.$options.el) {
vm.$mount(vm.$options.el)
}
@ -48,7 +61,7 @@ export function renderMixin (Vue: Class<Component>) {
Vue.prototype._render = function (): VNode {
const vm: Component = this
const prev = renderState.activeInstance
renderState.activeInstance = vm
renderState.activeInstance = vm._renderParent
if (!vm._isMounted) {
// render static sub-trees for once on initial render
renderStaticTrees(vm)

2
src/core/util/env.js

@ -15,7 +15,7 @@ export const devtools = inBrowser && window.__VUE_DEVTOOLS_GLOBAL_HOOK__
// UA sniffing for working around browser-specific quirks
const UA = inBrowser && window.navigator.userAgent.toLowerCase()
const isIos = UA && /(iphone|ipad|ipod|ios)/i.test(UA)
const iosVersionMatch = isIos && UA.match(/os ([\d_]+)/)
const iosVersionMatch = UA && isIos && UA.match(/os ([\d_]+)/)
const iosVersion = iosVersionMatch && iosVersionMatch[1].split('_')
// MutationObserver is unreliable in iOS 9.3 UIWebView

2
src/core/vdom/create-element.js

@ -36,7 +36,7 @@ export function renderElement (
): VNode | void {
// make sure to expose real self instead of proxy
const context: Component = this._self
const parent: Component | null = renderState.activeInstance
const parent: ?Component = renderState.activeInstance
if (!parent) {
process.env.NODE_ENV !== 'production' && warn(
'createElement cannot be called outside of component ' +

2
src/platforms/web/runtime/components/transition-control.js

@ -3,6 +3,8 @@
import { warn } from 'core/util/index'
export default {
name: 'transition-control',
_abstract: true,
props: {
mode: {
validator (val) {

Loading…
Cancel
Save