Skip to content

Commit

Permalink
component refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
yyx990803 committed Dec 18, 2013
1 parent e04553a commit 628c42c
Show file tree
Hide file tree
Showing 17 changed files with 112 additions and 258 deletions.
3 changes: 2 additions & 1 deletion component.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"src/directives/if.js",
"src/directives/repeat.js",
"src/directives/on.js",
"src/directives/model.js"
"src/directives/model.js",
"src/directives/component.js"
],
"dependencies": {
"component/emitter": "*"
Expand Down
67 changes: 30 additions & 37 deletions src/compiler.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,9 @@ function Compiler (vm, options) {

// set parent VM
// and register child id on parent
var childId = utils.attr(el, 'id')
var childId = utils.attr(el, 'component-id')
if (parent) {
parent.childCompilers.push(compiler)
def(vm, '$parent', parent.vm)
if (childId) {
compiler.childId = childId
Expand Down Expand Up @@ -217,18 +218,20 @@ CompilerProto.setupObserver = function () {
*/
CompilerProto.compile = function (node, root) {

var compiler = this
var compiler = this,
nodeType = node.nodeType,
tagName = node.tagName

if (node.nodeType === 1) { // a normal node
if (nodeType === 1 && tagName !== 'SCRIPT') { // a normal node

// skip anything with v-pre
if (utils.attr(node, 'pre') !== null) return

// special attributes to check
var repeatExp,
componentId,
componentExp,
partialId,
customElementFn = compiler.getOption('elements', node.tagName.toLowerCase())
directive

// It is important that we access these attributes
// procedurally because the order matters.
Expand All @@ -242,21 +245,25 @@ CompilerProto.compile = function (node, root) {
if (repeatExp = utils.attr(node, 'repeat')) {

// repeat block cannot have v-id at the same time.
var directive = Directive.parse(config.attrs.repeat, repeatExp, compiler, node)
directive = Directive.parse(config.attrs.repeat, repeatExp, compiler, node)
if (directive) {
compiler.bindDirective(directive)
}

// custom elements has 2nd highest priority
} else if (!root && customElementFn) {

addChild(customElementFn)

// v-component has 3rd highest priority
} else if (!root && (componentId = utils.attr(node, 'component'))) {
// v-component has 2nd highest priority
} else if (!root && (componentExp = utils.attr(node, 'component'))) {

var ChildVM = compiler.getOption('components', componentId)
if (ChildVM) addChild(ChildVM)
directive = Directive.parse(config.attrs.component, componentExp, compiler, node)
if (directive) {
// component directive is a bit different from the others.
// when it has no argument, it should be treated as a
// simple directive with its key as the argument.
if (componentExp.indexOf(':') === -1) {
directive.isSimple = true
directive.arg = directive.key
}
compiler.bindDirective(directive)
}

} else {

Expand All @@ -277,27 +284,12 @@ CompilerProto.compile = function (node, root) {
compiler.compileNode(node)
}

} else if (node.nodeType === 3) { // text node
} else if (nodeType === 3) { // text node

compiler.compileTextNode(node)

}

function addChild (Ctor) {
if (utils.isConstructor(Ctor)) {
var child = new Ctor({
el: node,
child: true,
compilerOptions: {
parentCompiler: compiler
}
})
compiler.childCompilers.push(child.$compiler)
} else {
// simply call the function
Ctor(node)
}
}
}

/**
Expand Down Expand Up @@ -412,13 +404,13 @@ CompilerProto.bindDirective = function (directive) {
binding.instances.push(directive)
directive.binding = binding

var value = binding.value
// invoke bind hook if exists
if (directive.bind) {
directive.bind(value)
directive.bind()
}

// set initial value
var value = binding.value
if (value !== undefined) {
if (binding.isComputed) {
directive.refresh(value)
Expand Down Expand Up @@ -454,11 +446,11 @@ CompilerProto.createBinding = function (key, isExp, isFn) {
bindings[key] = binding
// make sure the key exists in the object so it can be observed
// by the Observer!
Observer.ensurePath(compiler.vm, key)
if (binding.root) {
// this is a root level binding. we need to define getter/setters for it.
compiler.define(key, binding)
} else {
Observer.ensurePath(compiler.vm, key)
var parentKey = key.slice(0, key.lastIndexOf('.'))
if (!hasOwn.call(bindings, parentKey)) {
// this is a nested value binding, but the binding for its parent
Expand Down Expand Up @@ -488,9 +480,10 @@ CompilerProto.define = function (key, binding) {
// computed property
compiler.markComputed(binding)
} else if (type === 'Object' || type === 'Array') {
// observe objects later, becase there might be more keys
// to be added to it. we also want to emit all the set events
// after all values are available.
// observe objects later, because there might be more keys
// to be added to it during Observer.ensurePath().
// we also want to emit all the set events after all values
// are available.
compiler.observables.push(binding)
}

Expand Down
6 changes: 3 additions & 3 deletions src/deps-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ var Emitter = require('./emitter'),
function catchDeps (binding) {
if (binding.isFn) return
utils.log('\n─ ' + binding.key)
var depsHash = utils.hash()
var has = []
observer.on('get', function (dep) {
if (depsHash[dep.key]) return
depsHash[dep.key] = 1
if (has.indexOf(dep) > -1) return
has.push(dep)
utils.log(' └─ ' + dep.key)
binding.deps.push(dep)
dep.subs.push(binding)
Expand Down
40 changes: 40 additions & 0 deletions src/directives/component.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
var utils = require('../utils')

module.exports = {

bind: function () {
if (this.isSimple) {
this.build()
}
},

update: function (value) {
if (!this.component) {
this.build(value)
} else {
this.component.model = value
}
},

build: function (value) {
var Ctor = this.compiler.getOption('components', this.arg)
if (!Ctor) utils.warn('unknown component: ' + this.arg)
var options = {
el: this.el,
compilerOptions: {
parentCompiler: this.compiler
}
}
if (value) {
options.scope = {
model: value
}
}
this.component = new Ctor(options)
},

unbind: function () {
this.component.$destroy()
}

}
9 changes: 5 additions & 4 deletions src/directives/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ var utils = require('../utils'),

module.exports = {

on : require('./on'),
repeat : require('./repeat'),
model : require('./model'),
'if' : require('./if'),
on : require('./on'),
repeat : require('./repeat'),
model : require('./model'),
'if' : require('./if'),
component : require('./component'),

attr: function (value) {
this.el.setAttribute(this.arg, value)
Expand Down
11 changes: 1 addition & 10 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,6 @@ ViewModel.component = function (id, Ctor) {
return this
}

/**
* Allows user to register/retrieve a Custom element constructor
*/
ViewModel.element = function (id, Ctor) {
if (!Ctor) return utils.elements[id]
utils.elements[id] = utils.toConstructor(Ctor)
return this
}

/**
* Allows user to register/retrieve a template partial
*/
Expand Down Expand Up @@ -141,12 +132,12 @@ function inheritOptions (child, parent, topLevel) {
* that are used in compilation.
*/
var specialAttributes = [
'id',
'pre',
'text',
'repeat',
'partial',
'component',
'component-id',
'transition'
]

Expand Down
4 changes: 3 additions & 1 deletion src/observer.js
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,12 @@ function ensurePath (obj, key) {
if (!obj[sec]) obj[sec] = {}
obj = obj[sec]
}
if (typeOf(obj) === 'Object') {
var type = typeOf(obj)
if (type === 'Object' || type === 'Array') {
sec = path[i]
if (!(sec in obj)) obj[sec] = undefined
}
return obj[sec]
}

module.exports = {
Expand Down
16 changes: 2 additions & 14 deletions src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ var utils = module.exports = {
components : makeHash(),
partials : makeHash(),
transitions : makeHash(),
elements : makeHash(),

/**
* get an attribute and remove it.
Expand Down Expand Up @@ -141,30 +140,19 @@ var utils = module.exports = {
: null
},

isConstructor: function (obj) {
ViewModel = ViewModel || require('./viewmodel')
return obj.prototype instanceof ViewModel || obj === ViewModel
},

/**
* convert certain option values to the desired format.
*/
processOptions: function (options) {
var components = options.components,
partials = options.partials,
template = options.template,
elements = options.elements,
key
if (components) {
for (key in components) {
components[key] = utils.toConstructor(components[key])
}
}
if (elements) {
for (key in elements) {
elements[key] = utils.toConstructor(elements[key])
}
}
if (partials) {
for (key in partials) {
partials[key] = utils.toFragment(partials[key])
Expand All @@ -185,11 +173,11 @@ var utils = module.exports = {
},

/**
* warnings, thrown in all cases
* warnings, traces by default
* can be suppressed by `silent` option.
*/
warn: function() {
if (!config.silent && console) {
console.trace()
console.warn(join.call(arguments, ' '))
}
}
Expand Down
40 changes: 0 additions & 40 deletions test/functional/fixtures/custom-element.html

This file was deleted.

0 comments on commit 628c42c

Please sign in to comment.