在前面我们将一个模板字符串转换成了DOM,但是并没有对其做任何处理,接下来要做的事情就是去识别文本插值以及各种指令。这一篇文章主要介绍使用“Mustache”语法 (双大括号) 的文本插值。
compile 首先我们要对每一个节点进行遍历,compileNodeList
就是一个递归调用,如果节点下面有子节点就对其执行compileNodeList
,这样我们就可以对每个节点进行compileNode
处理。
在compileNode
中我们分别对文本节点和元素节点进行处理,这一篇文章主要讲文本插值,所以我们只看文本节点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function compile (el ) { if (el.hasChildNodes()) { compileNodeList(el.childNodes) } } function compileNodeList (nodeList ) { var node for (var i = 0 , l = nodeList.length; i < l; i++) { node = nodeList[i] compileNode(node) if (node.hasChildNodes()) { compileNodeList(node.childNodes) } } } function compileNode (node ) { var type = node.nodeType if (type === 3 && node.data.trim()) { compileTextNode(node) } }
对文本节点的处理 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function compileTextNode (node ) { var tokens = parseText(node.wholeText) if (!tokens) { return null } var frag = document .createDocumentFragment() var el, token for (var i = 0 , l = tokens.length; i < l; i++) { token = tokens[i] if (token.tag) { el = document .createTextNode(' ' ) new Watcher(data, token.value, function (value, oldValue ) { var attr = el.nodeType === 3 ? 'data' : 'textContent' ; el[attr] = value == null ? '' : value.toString() }); } else { el = document .createTextNode(token.value) } frag.appendChild(el) } replace(node, frag) }
工具方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 function parseText (text ) { var tagRE = /\{\{((?:.|\n)+?)\}\}/g if (!tagRE.test(text)) { return null } var tokens = [] var lastIndex = tagRE.lastIndex = 0 var match, index, html, value while (match = tagRE.exec(text)) { index = match.index if (index > lastIndex) { tokens.push({ value: text.slice(lastIndex, index) }) } value = match[1 ] tokens.push({ tag: true , value: value.trim(), }) lastIndex = index + match[0 ].length } if (lastIndex < text.length) { tokens.push({ value: text.slice(lastIndex) }) } return tokens }
Demo 查看DEMO