diff --git a/examples/template.html b/examples/template.html index d1231eb7f28..48d72b56afe 100644 --- a/examples/template.html +++ b/examples/template.html @@ -6,31 +6,26 @@ -
- - \ No newline at end of file diff --git a/src/compiler.js b/src/compiler.js index 692292c30cb..79c36fd1f2e 100644 --- a/src/compiler.js +++ b/src/compiler.js @@ -30,26 +30,17 @@ function Compiler (vm, options) { if (data) utils.extend(vm, data) // determine el - var tpl = options.template, - el = options.el - el = typeof el === 'string' - ? document.querySelector(el) - : el - if (el) { - var tplExp = tpl || el.getAttribute(config.prefix + '-template') - if (tplExp) { - el.innerHTML = utils.getTemplate(tplExp) || '' - el.removeAttribute(config.prefix + '-template') - } - } else if (tpl) { - var template = utils.getTemplate(tpl) - if (template) { - var tplHolder = document.createElement('div') - tplHolder.innerHTML = template - el = tplHolder.childNodes[0] - } - } - + var el = typeof options.el === 'string' + ? document.querySelector(options.el) + : options.el + ? options.el + : options.template + ? utils.makeTemplateNode(options) + : vm.templateNode + ? vm.templateNode.cloneNode(true) + : null + + if (!el) return utils.warn('invalid VM options.') utils.log('\nnew VM instance: ', el, '\n') // set stuff on the ViewModel diff --git a/src/main.js b/src/main.js index cce5e5a0cd6..acc11a7c0b0 100644 --- a/src/main.js +++ b/src/main.js @@ -56,8 +56,8 @@ api.compile = function (el, opts) { * and add extend method */ api.ViewModel = ViewModel - ViewModel.extend = function (options) { + // create child constructor var ExtendedVM = function (opts) { opts = opts || {} if (options.init) { @@ -69,16 +69,25 @@ ViewModel.extend = function (options) { } ViewModel.call(this, opts) } + // inherit from ViewModel var proto = ExtendedVM.prototype = Object.create(ViewModel.prototype) proto.constructor = ExtendedVM - if (options.props) utils.extend(proto, options.props) + // copy props + if (options.props) { + utils.extend(proto, options.props, function (key) { + return !(key in ViewModel.prototype) + }) + } + // register vm id so it can be found by sd-viewmodel if (options.id) { utils.registerVM(options.id, ExtendedVM) } + // convert string template into a node + // because cloneNode is faster than innerHTML + if (options.template) { + proto.templateNode = utils.makeTemplateNode(options) + } return ExtendedVM } -// collect templates on load -utils.collectTemplates() - module.exports = api \ No newline at end of file diff --git a/src/utils.js b/src/utils.js index 4e6c0a08840..73af4ff2a43 100644 --- a/src/utils.js +++ b/src/utils.js @@ -9,31 +9,17 @@ module.exports = { return toString.call(obj).slice(8, -1) }, - extend: function (obj, ext) { + extend: function (obj, ext, qualifier) { for (var key in ext) { + if (qualifier && !qualifier(key)) continue obj[key] = ext[key] } }, - collectTemplates: function () { - var selector = 'script[type="text/' + config.prefix + '-template"]', - templates = document.querySelectorAll(selector), - i = templates.length - while (i--) { - this.storeTemplate(templates[i]) - } - }, - - storeTemplate: function (template) { - var id = template.getAttribute(config.prefix + '-template-id') - if (id) { - templates[id] = template.innerHTML.trim() - } - template.parentNode.removeChild(template) - }, - - getTemplate: function (id) { - return templates[id] + makeTemplateNode: function (options) { + var node = document.createElement(options.tagName || 'div') + node.innerHTML = options.template + return node }, registerVM: function (id, VM) { diff --git a/test/unit/specs/api.js b/test/unit/specs/api.js index cc1048d55c8..139460b3eb5 100644 --- a/test/unit/specs/api.js +++ b/test/unit/specs/api.js @@ -37,6 +37,23 @@ describe('UNIT: API', function () { assert.strictEqual(utils.getVM('test'), Test) }) + it('should take options.template and work', function () { + var Test = seed.ViewModel.extend({ + tagName: 'p', + template: '{{hello}}haha', + data: { + hello: 'Ahaha' + } + }), + vm = new Test(), + text1 = vm.$el.querySelector('span').textContent, + text2 = vm.$el.querySelector('a').textContent + assert.ok(Test.prototype.templateNode instanceof HTMLElement) + assert.strictEqual(vm.$el.nodeName, 'P') + assert.strictEqual(text1, 'Ahaha') + assert.strictEqual(text2, 'haha') + }) + it('should call options.init when instantiating', function () { var called = false, Test = seed.ViewModel.extend({ init: function () {