From 0694a9bfb63350d2cb7ed992fee82e6a632ec74a Mon Sep 17 00:00:00 2001 From: Evan You Date: Tue, 12 Apr 2016 23:23:32 -0400 Subject: [PATCH] lifecycle hooks --- src/runtime-with-compiler.js | 2 +- src/runtime/instance/index.js | 28 +++++++++++----------- src/runtime/instance/lifecycle.js | 39 ++++++++++++++++++++++++++----- src/runtime/instance/render.js | 5 ++++ 4 files changed, 52 insertions(+), 22 deletions(-) diff --git a/src/runtime-with-compiler.js b/src/runtime-with-compiler.js index 91ef02c6..213f40ae 100644 --- a/src/runtime-with-compiler.js +++ b/src/runtime-with-compiler.js @@ -1,6 +1,6 @@ import config from './runtime/config' import { compile } from './compiler/index' -import { getOuterHTML, extend, query, warn } from './runtime/util/index' +import { getOuterHTML, query, warn } from './runtime/util/index' import Vue from './runtime/index' const mount = Vue.prototype.$mount diff --git a/src/runtime/instance/index.js b/src/runtime/instance/index.js index d3a2a493..6b06f0d0 100644 --- a/src/runtime/instance/index.js +++ b/src/runtime/instance/index.js @@ -1,36 +1,34 @@ import { initState, stateMixin } from './state' import { initRender, renderMixin } from './render' import { initEvents, eventsMixin } from './events' -import { initLifecycle, lifecycleMixin } from './lifecycle' +import { initLifecycle, lifecycleMixin, callHook } from './lifecycle' import { nextTick, mergeOptions } from '../util/index' let uid = 0 export default function Vue (options) { - options = options || {} - - this.$parent = options.parent - this.$root = this.$parent - ? this.$parent.$root - : this - this.$children = [] - this.$refs = {} // child vm references - this.$els = {} // element references - // a uid this._uid = uid++ // a flag to avoid this being observed this._isVue = true - options = this.$options = mergeOptions( + this.$parent = options && options.parent + this.$root = this.$parent ? this.$parent.$root : this + this.$refs = {} + this.$els = {} + + // merge options + this.$options = mergeOptions( this.constructor.options, - options, + options || {}, this ) - initState(this) - initEvents(this) initLifecycle(this) + initEvents(this) + callHook(this, 'init') + initState(this) + callHook(this, 'created') initRender(this) } diff --git a/src/runtime/instance/lifecycle.js b/src/runtime/instance/lifecycle.js index 842ea1cf..4e17c97d 100644 --- a/src/runtime/instance/lifecycle.js +++ b/src/runtime/instance/lifecycle.js @@ -1,13 +1,40 @@ -export function initLifecycle (vm) { +export function callHook (vm, hook) { + vm.$emit('pre-hook:' + hook) + var handlers = vm.$options[hook] + if (handlers) { + for (var i = 0, j = handlers.length; i < j; i++) { + handlers[i].call(vm) + } + } + vm.$emit('hook:' + hook) +} +export function initLifecycle (vm) { + vm._isDestroyed = false + vm._isBeingDestroyed = false } export function lifecycleMixin (Vue) { - Vue.prototype.$mount = function () { - - } - Vue.prototype.$destroy = function () { - + if (this._isDestroyed) { + return + } + this._callHook('beforeDestroy') + this._isBeingDestroyed = true + // teardown watchers + let i = this._watchers.length + while (i--) { + this._watchers[i].teardown() + } + // remove reference from data ob + // frozen object may not have observer. + if (this._data.__ob__) { + this._data.__ob__.removeVm(this) + } + // call the last hook... + this._isDestroyed = true + this._callHook('destroyed') + // turn off all instance listeners. + this.$off() } } diff --git a/src/runtime/instance/render.js b/src/runtime/instance/render.js index ef102b27..e631b864 100644 --- a/src/runtime/instance/render.js +++ b/src/runtime/instance/render.js @@ -1,6 +1,7 @@ import Watcher from '../observer/watcher' import { query } from '../util/index' import { h, patch } from '../vdom/index' +import { callHook } from './lifecycle' export function initRender (vm) { const el = vm.$options.el @@ -13,19 +14,23 @@ export function renderMixin (Vue) { Vue.prototype.__h__ = h Vue.prototype._update = function (vtree) { + callHook(this, 'beforeUpdate') if (!this._tree) { patch(this.$el, vtree) } else { patch(this._tree, vtree) } this._tree = vtree + callHook(this, 'updated') } Vue.prototype.$mount = function (el) { + callHook(this, 'beforeMount') this.$el = el ? query(el) : document.createElement('div') this.$el.innerHTML = '' this._watcher = new Watcher(this, this.$options.render, this._update) this._update(this._watcher.value) + callHook(this, 'mounted') } Vue.prototype.$forceUpdate = function () {