Skip to content

Commit

Permalink
refactor component scope compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 2, 2014
1 parent 1165cd2 commit 25d5dea
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 143 deletions.
79 changes: 3 additions & 76 deletions src/api/lifecycle.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,85 +51,12 @@ function ready () {
}

/**
* 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
* @public
* Teardown the instance, simply delegate to the internal
* _destroy.
*/

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 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()
this._destroy(remove, deferCleanup)
}

/**
Expand Down
35 changes: 9 additions & 26 deletions src/compiler/transclude.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,53 +44,36 @@ function transcludeTemplate (el, options) {
if (!frag) {
_.warn('Invalid template option: ' + template)
} else {
collectRawContent(el)
var rawContent = options._content || _.extractContent(el)
if (options.replace) {
if (frag.childNodes.length > 1) {
transcludeContent(frag)
transcludeContent(frag, rawContent)
return frag
} else {
var replacer = frag.firstChild
_.copyAttributes(el, replacer)
transcludeContent(replacer)
transcludeContent(replacer, rawContent)
return replacer
}
} else {
el.appendChild(frag)
transcludeContent(el)
transcludeContent(el, rawContent)
return el
}
}
}

/**
* Collect raw content inside $el before they are
* replaced by template content.
*/

var rawContent
function collectRawContent (el) {
var child
rawContent = null
if (el.hasChildNodes()) {
rawContent = document.createElement('div')
/* jshint boss:true */
while (child = el.firstChild) {
rawContent.appendChild(child)
}
}
}

/**
* Resolve <content> insertion points mimicking the behavior
* of the Shadow DOM spec:
*
* http://w3c.github.io/webcomponents/spec/shadow/#insertion-points
*
* @param {Element|DocumentFragment} el
* @param {Element} raw
*/

function transcludeContent (el) {
function transcludeContent (el, raw) {
var outlets = getOutlets(el)
var i = outlets.length
if (!i) return
Expand All @@ -99,10 +82,10 @@ function transcludeContent (el) {
// for each outlet.
while (i--) {
outlet = outlets[i]
if (rawContent) {
if (raw) {
select = outlet.getAttribute('select')
if (select) { // select content
selected = rawContent.querySelectorAll(select)
selected = raw.querySelectorAll(select)
outlet.content = _.toArray(
selected.length
? selected
Expand All @@ -124,7 +107,7 @@ function transcludeContent (el) {
}
// finally insert the main content
if (main) {
insertContentAt(main, _.toArray(rawContent.childNodes))
insertContentAt(main, _.toArray(raw.childNodes))
}
}

Expand Down
4 changes: 1 addition & 3 deletions src/directive.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ var expParser = require('./parsers/expression')
* - {String} [arg]
* - {Array<Object>} [filters]
* @param {Object} def - directive definition object
* @param {Function} [linker] - pre-compiled linker function
* @constructor
*/

function Directive (name, el, vm, descriptor, def, linker) {
function Directive (name, el, vm, descriptor, def) {
// public
this.name = name
this.el = el
Expand All @@ -33,7 +32,6 @@ function Directive (name, el, vm, descriptor, def, linker) {
this.arg = descriptor.arg
this.filters = _.resolveFilters(vm, descriptor.filters)
// private
this._linker = linker
this._locked = false
this._bound = false
// init
Expand Down
24 changes: 3 additions & 21 deletions src/directives/component.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
var _ = require('../util')
var compile = require('../compiler/compile')
var templateParser = require('../parsers/template')

module.exports = {
Expand Down Expand Up @@ -30,12 +29,6 @@ module.exports = {
if (this.keepAlive) {
this.cache = {}
}
// compile parent scope content
this.parentLinkFn = compile(
this.el, this.vm.$options,
true, // partial
true // asParent
)
// if static, build right now.
if (!this._isDynamicLiteral) {
this.resolveCtor(this.expression)
Expand Down Expand Up @@ -83,14 +76,10 @@ module.exports = {
var vm = this.vm
var el = templateParser.clone(this.el)
if (this.Ctor) {
var parentUnlinkFn
if (this.parentLinkFn) {
parentUnlinkFn = this.parentLinkFn(vm, el)
}
var child = vm.$addChild({
el: el
el: el,
_asComponent: true
}, this.Ctor)
child._parentUnlinkFn = parentUnlinkFn
if (this.keepAlive) {
this.cache[this.ctorId] = child
}
Expand All @@ -108,9 +97,6 @@ module.exports = {
if (!child || this.keepAlive) {
return
}
if (child._parentUnlinkFn) {
child._parentUnlinkFn()
}
// the sole purpose of `deferCleanup` is so that we can
// "deactivate" the vm right now and perform DOM removal
// later.
Expand Down Expand Up @@ -201,11 +187,7 @@ module.exports = {
// destroy all keep-alive cached instances
if (this.cache) {
for (var key in this.cache) {
var child = this.cache[key]
if (child._parentUnlinkFn) {
child._parentUnlinkFn()
}
child.$destroy()
this.cache[key].$destroy()
}
this.cache = null
}
Expand Down
23 changes: 14 additions & 9 deletions src/directives/repeat.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,26 @@ module.exports = {
// important: transclude with no options, just
// to ensure block start and block end
this.template = transclude(this.template)
this._linker = compile(this.template, options)
this._linkFn = compile(this.template, options)
} else {
this._asComponent = true
var tokens = textParser.parse(id)
if (!tokens) { // static component
var Ctor = this.Ctor = options.components[id]
_.assertAsset(Ctor, 'component', id)
if (Ctor) {
// If there's no parent scope directives and no
// content to be transcluded, we can optimize the
// rendering by pre-transcluding + compiling here
// and provide a link function to every instance.
if (!this.el.hasChildNodes() &&
!this.el.hasAttributes()) {
// merge an empty object with owner vm as parent
// so child vms can access parent assets.
var merged = mergeOptions(
Ctor.options,
{},
{ $parent: this.vm }
)
var merged = mergeOptions(Ctor.options, {}, {
$parent: this.vm
})
this.template = transclude(this.template, merged)
this._linker = compile(this.template, merged)
this._linkFn = compile(this.template, merged)
}
} else {
// to be resolved later
Expand Down Expand Up @@ -274,7 +278,8 @@ module.exports = {
var Ctor = this.Ctor || this.resolveCtor(data, meta)
var vm = this.vm.$addChild({
el: templateParser.clone(this.template),
_linker: this._linker,
_asComponent: this._asComponent,
_linkFn: this._linkFn,
_meta: meta,
data: data,
inherit: this.inherit
Expand Down
Loading

0 comments on commit 25d5dea

Please sign in to comment.