第一步、解析模板转成token
const templateStr1 = "我今天买了一个{{thing}},心情还蛮{{mood}}的"
const data = {
thing: "玩具",
mood: "开心",
}
function templateToTokens(templateStr) {
console.log(templateStr)
let tokens = []
let pos = 0
let tail = templateStr
while (tail !== '') {
console.log(tail,"进来了")
let idx = tail.indexOf("{{")
if (idx < 0) {
tokens.push(["text", tail])
tail = ""
break
}
let text = tail.substring(pos, idx)
tokens.push(["text", text])
tail = tail.slice(idx + 2)
idx = tail.indexOf("}}")
let name = tail.substring(pos, idx)
tokens.push(["name", name])
tail = tail.slice(idx + 2)
}
return tokens
}
const tempStr2 = `
<ol>
{{#student}}
<li>{{name}}</li>
<li>{{age}}</li>
<li>{{sex}}</li>
{{/student}}
</ol>
`
if (name.startsWith("#")) {
tokens.push(["#", name.substring(1)])
} else if (name.startsWith("/")) {
tokens.push(["/", name.substring(1)])
} else {
tokens.push(["name", name])
}
}
第二步、折叠数组
当模板字符串解析成token后,的数组结构是
[['text', '\n <ol>\n '],
['#', 'student'],
['text', '\n <li>'],
...]
这并不符合我们的预期,我们需要将数组这折叠成为
[
['text', '\n <ol>\n '],
['#', 'student',[
['text', '\n <li>'],
....
]],
['text', '\n </ol>\n '],
]
function nestedTokens(tokens) {
let resultTokens = []
let section = []
let colloctor = resultTokens
for (let i = 0; i < tokens.length; i++) {
let token = tokens[i]
if (token[0] === "#") {
section.push(token)
colloctor.push(token)
colloctor = token[2] = []
} else if (token[0] === "/") {
section.pop()
colloctor = section.length > 0 ? section[section.length - 1][2] : resultTokens
} else {
colloctor.push(token)
}
}
return resultTokens
}
最后一步,变成dom字符串
function renderTemplate(tokens, data) {
console.log(tokens, data, "tokens,data")
let resultStr = ""
for (let i = 0; i < tokens.length; i++) {
const token = tokens[i]
if (token[0] == "text") {
resultStr += token[1]
} else if (token[0] == "#") {
const tempData = lookup(data, token[1])
console.log(tempData, "tempData")
let tempStr = ""
for (let j = 0; j < tempData.length; j++) {
let oneData = tempData[j]
tempStr += renderTemplate(token[2], oneData)
}
resultStr += tempStr
} else {
resultStr += lookup({ ...data, ".": data }, token[1])
}
}
console.log(resultStr, "resultStr")
return resultStr
}
在过程中会发现一个问题就是处理当token[0]是name的时候,我们需要去数据去寻找所对应的值,所以单独封装一个函数lookup去获取这个值
function lookup(data, keyName) {
let result = data
if (keyName.indexOf(".") > 0) {
let keys = keyName.split(".")
for (let i = 0; i < keys; i++) {
let key = keys[i]
result = result[key]
}
} else {
return result[keyName]
}
}