|
@@ -18,15 +18,36 @@ var transclude = require('../compiler/transclude')
|
|
|
|
|
|
|
|
exports._compile = function (el) {
|
|
exports._compile = function (el) {
|
|
|
var options = this.$options
|
|
var options = this.$options
|
|
|
- if (options._linker) {
|
|
|
|
|
|
|
+ if (options._linkFn) {
|
|
|
this._initElement(el)
|
|
this._initElement(el)
|
|
|
- options._linker(this, el)
|
|
|
|
|
|
|
+ options._linkFn(this, el)
|
|
|
} else {
|
|
} else {
|
|
|
var raw = el
|
|
var raw = el
|
|
|
- el = transclude(el, options)
|
|
|
|
|
|
|
+ if (options._asComponent) {
|
|
|
|
|
+ // separate container element and content
|
|
|
|
|
+ var content = options._content = _.extractContent(raw)
|
|
|
|
|
+ // create two separate linekrs for container and content
|
|
|
|
|
+ var containerLinkFn =
|
|
|
|
|
+ compile(raw, options, true, true)
|
|
|
|
|
+ if (content) {
|
|
|
|
|
+ var contentLinkFn =
|
|
|
|
|
+ compile(content, options, true, true)
|
|
|
|
|
+ // call content linker now, before transclusion
|
|
|
|
|
+ this._contentUnlinkFn =
|
|
|
|
|
+ contentLinkFn(options._parent, content)
|
|
|
|
|
+ }
|
|
|
|
|
+ // tranclude, this possibly replaces original
|
|
|
|
|
+ el = transclude(el, options)
|
|
|
|
|
+ // now call the container linker on the resolved el
|
|
|
|
|
+ this._containerUnlinkFn =
|
|
|
|
|
+ containerLinkFn(options._parent, el)
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // simply transclude
|
|
|
|
|
+ el = transclude(el, options)
|
|
|
|
|
+ }
|
|
|
this._initElement(el)
|
|
this._initElement(el)
|
|
|
- var linker = compile(el, options)
|
|
|
|
|
- linker(this, el)
|
|
|
|
|
|
|
+ var linkFn = compile(el, options)
|
|
|
|
|
+ linkFn(this, el)
|
|
|
if (options.replace) {
|
|
if (options.replace) {
|
|
|
_.replace(raw, el)
|
|
_.replace(raw, el)
|
|
|
}
|
|
}
|
|
@@ -61,11 +82,98 @@ exports._initElement = function (el) {
|
|
|
* @param {Node} node - target node
|
|
* @param {Node} node - target node
|
|
|
* @param {Object} desc - parsed directive descriptor
|
|
* @param {Object} desc - parsed directive descriptor
|
|
|
* @param {Object} def - directive definition object
|
|
* @param {Object} def - directive definition object
|
|
|
- * @param {Function} [linker] - pre-compiled linker fn
|
|
|
|
|
*/
|
|
*/
|
|
|
|
|
|
|
|
-exports._bindDir = function (name, node, desc, def, linker) {
|
|
|
|
|
|
|
+exports._bindDir = function (name, node, desc, def) {
|
|
|
this._directives.push(
|
|
this._directives.push(
|
|
|
- new Directive(name, node, this, desc, def, linker)
|
|
|
|
|
|
|
+ new Directive(name, node, this, desc, def)
|
|
|
)
|
|
)
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Teardown an instance, unobserves the data, unbind all the
|
|
|
|
|
+ * directives, turn off all the event listeners, etc.
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param {Boolean} remove - whether to remove the DOM node.
|
|
|
|
|
+ * @param {Boolean} deferCleanup - if true, defer cleanup to
|
|
|
|
|
+ * be called later
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+exports._destroy = function (remove, deferCleanup) {
|
|
|
|
|
+ if (this._isBeingDestroyed) {
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+ this._callHook('beforeDestroy')
|
|
|
|
|
+ this._isBeingDestroyed = true
|
|
|
|
|
+ var i
|
|
|
|
|
+ // remove self from parent. only necessary
|
|
|
|
|
+ // if parent is not being destroyed as well.
|
|
|
|
|
+ var parent = this.$parent
|
|
|
|
|
+ if (parent && !parent._isBeingDestroyed) {
|
|
|
|
|
+ i = parent._children.indexOf(this)
|
|
|
|
|
+ parent._children.splice(i, 1)
|
|
|
|
|
+ }
|
|
|
|
|
+ // destroy all children.
|
|
|
|
|
+ if (this._children) {
|
|
|
|
|
+ i = this._children.length
|
|
|
|
|
+ while (i--) {
|
|
|
|
|
+ this._children[i].$destroy()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // teardown parent linkers
|
|
|
|
|
+ if (this._containerUnlinkFn) {
|
|
|
|
|
+ this._containerUnlinkFn()
|
|
|
|
|
+ }
|
|
|
|
|
+ if (this._contentUnlinkFn) {
|
|
|
|
|
+ this._contentUnlinkFn()
|
|
|
|
|
+ }
|
|
|
|
|
+ // teardown all directives. this also tearsdown all
|
|
|
|
|
+ // directive-owned watchers. intentionally check for
|
|
|
|
|
+ // directives array length on every loop since directives
|
|
|
|
|
+ // that manages partial compilation can splice ones out
|
|
|
|
|
+ for (i = 0; i < this._directives.length; i++) {
|
|
|
|
|
+ this._directives[i]._teardown()
|
|
|
|
|
+ }
|
|
|
|
|
+ // teardown all user watchers.
|
|
|
|
|
+ for (i in this._userWatchers) {
|
|
|
|
|
+ this._userWatchers[i].teardown()
|
|
|
|
|
+ }
|
|
|
|
|
+ // remove reference to self on $el
|
|
|
|
|
+ if (this.$el) {
|
|
|
|
|
+ this.$el.__vue__ = null
|
|
|
|
|
+ }
|
|
|
|
|
+ // remove DOM element
|
|
|
|
|
+ var self = this
|
|
|
|
|
+ if (remove && this.$el) {
|
|
|
|
|
+ this.$remove(function () {
|
|
|
|
|
+ self._cleanup()
|
|
|
|
|
+ })
|
|
|
|
|
+ } else if (!deferCleanup) {
|
|
|
|
|
+ this._cleanup()
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Clean up to ensure garbage collection.
|
|
|
|
|
+ * This is called after the leave transition if there
|
|
|
|
|
+ * is any.
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+exports._cleanup = function () {
|
|
|
|
|
+ // remove reference from data ob
|
|
|
|
|
+ this._data.__ob__.removeVm(this)
|
|
|
|
|
+ this._data =
|
|
|
|
|
+ this._watchers =
|
|
|
|
|
+ this._userWatchers =
|
|
|
|
|
+ this._watcherList =
|
|
|
|
|
+ this.$el =
|
|
|
|
|
+ this.$parent =
|
|
|
|
|
+ this.$root =
|
|
|
|
|
+ this._children =
|
|
|
|
|
+ this._directives = null
|
|
|
|
|
+ // call the last hook...
|
|
|
|
|
+ this._isDestroyed = true
|
|
|
|
|
+ this._callHook('destroyed')
|
|
|
|
|
+ // turn off all instance listeners.
|
|
|
|
|
+ this.$off()
|
|
|
}
|
|
}
|