mirror of https://github.com/vuejs/vue.git
Allow template nodes to be passed as a template option
Split the parsing/switching logic of the type of template option provided into the `template-parser` module and refactored `fragment` module to only convert string -> document fragment
This commit is contained in:
parent
fe996b3889
commit
66f4708643
|
|
@ -18,6 +18,7 @@
|
|||
"src/observer.js",
|
||||
"src/directive.js",
|
||||
"src/exp-parser.js",
|
||||
"src/template-parser.js",
|
||||
"src/text-parser.js",
|
||||
"src/deps-parser.js",
|
||||
"src/filters.js",
|
||||
|
|
@ -34,4 +35,4 @@
|
|||
"src/directives/partial.js",
|
||||
"src/directives/view.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,29 +30,12 @@ map.rect = [1, '<svg xmlns="http://www.w3.org/2000/svg" version="1.1">','</svg>'
|
|||
|
||||
var TAG_RE = /<([\w:]+)/
|
||||
|
||||
module.exports = function (template) {
|
||||
|
||||
if (typeof template !== 'string') {
|
||||
return template
|
||||
}
|
||||
|
||||
// template by ID
|
||||
if (template.charAt(0) === '#') {
|
||||
var templateNode = document.getElementById(template.slice(1))
|
||||
if (!templateNode) return
|
||||
// if its a template tag and the browser supports it,
|
||||
// its content is already a document fragment!
|
||||
if (templateNode.tagName === 'TEMPLATE' && templateNode.content) {
|
||||
return templateNode.content
|
||||
}
|
||||
template = templateNode.innerHTML
|
||||
}
|
||||
|
||||
module.exports = function (templateString) {
|
||||
var frag = document.createDocumentFragment(),
|
||||
m = TAG_RE.exec(template)
|
||||
m = TAG_RE.exec(templateString)
|
||||
// text only
|
||||
if (!m) {
|
||||
frag.appendChild(document.createTextNode(template))
|
||||
frag.appendChild(document.createTextNode(templateString))
|
||||
return frag
|
||||
}
|
||||
|
||||
|
|
@ -63,7 +46,7 @@ module.exports = function (template) {
|
|||
suffix = wrap[2],
|
||||
node = document.createElement('div')
|
||||
|
||||
node.innerHTML = prefix + template.trim() + suffix
|
||||
node.innerHTML = prefix + templateString.trim() + suffix
|
||||
while (depth--) node = node.lastChild
|
||||
|
||||
// one element
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ assetTypes.forEach(function (type) {
|
|||
}
|
||||
if (!value) return hash[id]
|
||||
if (type === 'partial') {
|
||||
value = utils.toFragment(value)
|
||||
value = utils.parseTemplateOption(value)
|
||||
} else if (type === 'component') {
|
||||
value = utils.toConstructor(value)
|
||||
} else if (type === 'filter') {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
var toFragment = require('./fragment');
|
||||
|
||||
/**
|
||||
* Parses a template string or node and normalizes it into a
|
||||
* a node that can be used as a partial of a template option
|
||||
*
|
||||
* Possible values include
|
||||
* id selector: '#some-template-id'
|
||||
* template string: '<div><span>my template</span></div>'
|
||||
* DocumentFragment object
|
||||
* Node object of type Template
|
||||
*/
|
||||
module.exports = function(template) {
|
||||
var templateNode;
|
||||
|
||||
if (template instanceof window.DocumentFragment) {
|
||||
// if the template is already a document fragment -- do nothing
|
||||
return template
|
||||
}
|
||||
|
||||
if (typeof template === 'string') {
|
||||
// template by ID
|
||||
if (template.charAt(0) === '#') {
|
||||
templateNode = document.getElementById(template.slice(1))
|
||||
if (!templateNode) return
|
||||
} else {
|
||||
return toFragment(template)
|
||||
}
|
||||
} else if (template.nodeType) {
|
||||
templateNode = template
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
// if its a template tag and the browser supports it,
|
||||
// its content is already a document fragment!
|
||||
if (templateNode.tagName === 'TEMPLATE' && templateNode.content) {
|
||||
return templateNode.content
|
||||
}
|
||||
|
||||
if (templateNode.tagName === 'SCRIPT') {
|
||||
return toFragment(templateNode.innerHTML)
|
||||
}
|
||||
|
||||
return toFragment(templateNode.outerHTML);
|
||||
}
|
||||
|
|
@ -32,6 +32,11 @@ var utils = module.exports = {
|
|||
*/
|
||||
toFragment: require('./fragment'),
|
||||
|
||||
/**
|
||||
* Parse the various types of template options
|
||||
*/
|
||||
parseTemplateOption: require('./template-parser.js'),
|
||||
|
||||
/**
|
||||
* get a value from an object keypath
|
||||
*/
|
||||
|
|
@ -226,7 +231,7 @@ var utils = module.exports = {
|
|||
}
|
||||
if (partials) {
|
||||
for (key in partials) {
|
||||
partials[key] = utils.toFragment(partials[key])
|
||||
partials[key] = utils.parseTemplateOption(partials[key])
|
||||
}
|
||||
}
|
||||
if (filters) {
|
||||
|
|
@ -235,7 +240,7 @@ var utils = module.exports = {
|
|||
}
|
||||
}
|
||||
if (template) {
|
||||
options.template = utils.toFragment(template)
|
||||
options.template = utils.parseTemplateOption(template)
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
describe('Utils', function () {
|
||||
afterEach(cleanupMocks)
|
||||
|
||||
var utils = require('vue/src/utils'),
|
||||
config = require('vue/src/config')
|
||||
|
|
@ -215,7 +216,7 @@ describe('Utils', function () {
|
|||
|
||||
describe('toFragment', function () {
|
||||
|
||||
it('should convert a string tempalte to a documentFragment', function () {
|
||||
it('should convert a string template to a documentFragment', function () {
|
||||
var template = '<div class="a">hi</div><p>ha</p>',
|
||||
frag = utils.toFragment(template)
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
|
|
@ -223,20 +224,6 @@ describe('Utils', function () {
|
|||
assert.equal(frag.querySelector('p').textContent, 'ha')
|
||||
})
|
||||
|
||||
it('should also work if the string is an ID selector', function () {
|
||||
var id = 'utils-template-to-fragment',
|
||||
template = '<div class="a">hi</div><p>ha</p>',
|
||||
el = document.createElement('template')
|
||||
el.id = id
|
||||
el.innerHTML = template
|
||||
document.getElementById('test').appendChild(el)
|
||||
|
||||
var frag = utils.toFragment('#' + id)
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
assert.equal(frag.querySelector('.a').textContent, 'hi')
|
||||
assert.equal(frag.querySelector('p').textContent, 'ha')
|
||||
})
|
||||
|
||||
it('should work with table elements', function () {
|
||||
var frag = utils.toFragment('<td></td>')
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
|
|
@ -252,6 +239,75 @@ describe('Utils', function () {
|
|||
|
||||
})
|
||||
|
||||
describe('parseTemplateOption', function () {
|
||||
|
||||
afterEach(cleanupMocks)
|
||||
|
||||
it('should convert a string template to a documentFragment', function () {
|
||||
var template = '<div class="a">hi</div><p>ha</p>',
|
||||
frag = utils.parseTemplateOption(template)
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
assert.equal(frag.querySelector('.a').textContent, 'hi')
|
||||
assert.equal(frag.querySelector('p').textContent, 'ha')
|
||||
})
|
||||
|
||||
describe('id selector', function() {
|
||||
it('should work with a TEMPLATE tag', function() {
|
||||
var id = 'utils-template-parse-template-option-template-tag',
|
||||
template = '<div class="a">hi</div><p>ha</p>',
|
||||
el = document.createElement('template')
|
||||
el.id = id
|
||||
el.innerHTML = template
|
||||
appendMock(el)
|
||||
|
||||
var frag = utils.parseTemplateOption('#' + id)
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
assert.equal(frag.querySelector('.a').textContent, 'hi')
|
||||
assert.equal(frag.querySelector('p').textContent, 'ha')
|
||||
})
|
||||
|
||||
it('should work with a DIV tag', function() {
|
||||
var id = 'utils-template-parse-template-option-div-tag',
|
||||
template = '<div class="a">hi</div><p>ha</p>',
|
||||
el = document.createElement('div')
|
||||
el.id = id
|
||||
el.innerHTML = template
|
||||
appendMock(el)
|
||||
|
||||
var frag = utils.parseTemplateOption('#' + id)
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
assert.equal(frag.querySelector('.a').textContent, 'hi')
|
||||
assert.equal(frag.querySelector('p').textContent, 'ha')
|
||||
})
|
||||
})
|
||||
|
||||
describe('when passed a Node', function() {
|
||||
it('should work with a TEMPLATE tag', function() {
|
||||
var el = document.createElement('template')
|
||||
el.innerHTML = '<div class="a">hi</div><p>ha</p>'
|
||||
|
||||
var frag = utils.parseTemplateOption(el)
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
assert.equal(frag.querySelector('.a').textContent, 'hi')
|
||||
assert.equal(frag.querySelector('p').textContent, 'ha')
|
||||
})
|
||||
|
||||
it('should work with a DIV tag', function() {
|
||||
var el = document.createElement('div')
|
||||
el.innerHTML = '<span class="a">hi</span><p>ha</p>'
|
||||
|
||||
var frag = utils.parseTemplateOption(el)
|
||||
assert.ok(frag instanceof window.DocumentFragment)
|
||||
|
||||
assert.equal(frag.firstChild.outerHTML, el.outerHTML)
|
||||
assert.equal(frag.querySelector('.a').textContent, 'hi')
|
||||
assert.equal(frag.querySelector('p').textContent, 'ha')
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
})
|
||||
|
||||
describe('toConstructor', function () {
|
||||
|
||||
it('should convert an non-VM object to a VM constructor', function () {
|
||||
|
|
@ -270,6 +326,17 @@ describe('Utils', function () {
|
|||
|
||||
describe('processOptions', function () {
|
||||
|
||||
beforeEach(function() {
|
||||
var id = 'utils-template-to-fragment',
|
||||
template = '<div class="a">hi</div><p>ha</p>',
|
||||
el = document.createElement('template')
|
||||
el.id = id
|
||||
el.innerHTML = template
|
||||
appendMock(el)
|
||||
})
|
||||
|
||||
afterEach(cleanupMocks)
|
||||
|
||||
var options = {
|
||||
partials: {
|
||||
a: '#utils-template-to-fragment',
|
||||
|
|
|
|||
|
|
@ -7,10 +7,18 @@ function mock (id, html, attrs) {
|
|||
el.setAttribute(attr, attrs[attr])
|
||||
}
|
||||
}
|
||||
document.getElementById('test').appendChild(el)
|
||||
appendMock(el)
|
||||
return el
|
||||
}
|
||||
|
||||
function appendMock(el) {
|
||||
document.getElementById('test').appendChild(el)
|
||||
}
|
||||
|
||||
function cleanupMocks() {
|
||||
document.getElementById('test').innerHTML = ''
|
||||
}
|
||||
|
||||
function mockHTMLEvent (type) {
|
||||
var e = document.createEvent('HTMLEvents')
|
||||
e.initEvent(type, true, true)
|
||||
|
|
|
|||
Loading…
Reference in New Issue