UNPKG

silk-gui

Version:

GUI for developers and Node OS

166 lines (156 loc) 4.26 kB
var _ = require('../util') var Directive = require('../directive') var compile = require('../compiler/compile') var transclude = require('../compiler/transclude') /** * Transclude, compile and link element. * * If a pre-compiled linker is available, that means the * passed in element will be pre-transcluded and compiled * as well - all we need to do is to call the linker. * * Otherwise we need to call transclude/compile/link here. * * @param {Element} el * @return {Element} */ exports._compile = function (el) { var options = this.$options if (options._linkFn) { // pre-transcluded with linker, just use it this._initElement(el) options._linkFn(this, el) } else { // transclude and init element // transclude can potentially replace original // so we need to keep reference var original = el el = transclude(el, options) this._initElement(el) // compile and link the rest compile(el, options)(this, el) // finally replace original if (options.replace) { _.replace(original, el) } } return el } /** * Initialize instance element. Called in the public * $mount() method. * * @param {Element} el */ exports._initElement = function (el) { if (el instanceof DocumentFragment) { this._isBlock = true this.$el = this._blockStart = el.firstChild this._blockEnd = el.lastChild this._blockFragment = el } else { this.$el = el } this.$el.__vue__ = this this._callHook('beforeCompile') } /** * Create and bind a directive to an element. * * @param {String} name - directive name * @param {Node} node - target node * @param {Object} desc - parsed directive descriptor * @param {Object} def - directive definition object * @param {Vue|undefined} host - transclusion host component */ exports._bindDir = function (name, node, desc, def, host) { this._directives.push( new Directive(name, node, this, desc, def, host) ) } /** * 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) } // same for transclusion host. var host = this._host if (host && !host._isBeingDestroyed) { i = host._transCpnts.indexOf(this) host._transCpnts.splice(i, 1) } // destroy all children. i = this._children.length while (i--) { this._children[i].$destroy() } // 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. var watcher for (i in this._userWatchers) { watcher = this._userWatchers[i] if (watcher) { watcher.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._transCpnts = this._directives = null // call the last hook... this._isDestroyed = true this._callHook('destroyed') // turn off all instance listeners. this.$off() }