UNPKG

magix

Version:

view manager framewrok

157 lines (153 loc) 5.85 kB
let TO_VDOM_SELF_CLOSE = { input: 1, br: 1, hr: 1, img: 1, embed: 1, source: 1, area: 1, param: 1, col: 1, track: 1, wbr: 1 }; let TO_VDOM_OpenReg = /^<([a-z\d]+)((?:\s+[-A-Za-z\d_]+(?:="[^"]*")?)*)\s*(\/?)>/, TO_VDOM_AttrReg = /([-A-Za-z\d_]+)(?:="([^"]*)")?/g, TO_VDOM_CloseReg = /^<\/[a-z\d]+>/; let TO_VDOM = input => { let count = input.length, current = 0, last = 0, chars, currentParent = { '@{~v#node.reused}': {}, '@{~v#node.children}': [], '@{~v#node.html}': input }, index, html = input, match, tag, attrs, stack = [currentParent], moveLength, diffChildren, em, amap, text, unary, compareKey;//新旧vnode的比较key while (current < count) { chars = 1; if (html[0] == '<') { if (html[1] == '/') { match = html.match(TO_VDOM_CloseReg); if (match) { em = stack.pop(); attrs = input.substring(em['@{~v#content.start.pos}'], current); if (em['@{~v#node.tag}'] == 'textarea') { em['@{~v#node.attrs}'].push({ '@{~v#node.attrs.key}': G_VALUE, '@{~v#node.attrs.value}': attrs }); em['@{~v#node.attrs.map}'][G_VALUE] = attrs; em['@{~v#node.children}'] = G_EMPTY_ARRAY; } else { em['@{~v#node.html}'] = attrs; } currentParent = stack[stack.length - 1]; current += moveLength = match[0].length; em['@{~v#node.outer.html}'] = input.substring(em['@{~v#node.start.pos}'], current); chars = 0; } } else { match = html.match(TO_VDOM_OpenReg); if (match) { tag = match[1]; chars = match[0]; attrs = []; amap = {}; compareKey = G_EMPTY; diffChildren = V_SPECIAL_PROPS[tag]; match[2].replace(TO_VDOM_AttrReg, (m, key, value) => { value = value || G_EMPTY; if (key == 'id') {//如果有id优先使用 compareKey = value; } else if (key == G_MX_VIEW && value && !compareKey) { //否则如果是组件,则使用组件的路径做为key compareKey = G_ParseUri(value)[G_PATH]; } else if (key == G_Tag_Key && !compareKey) { compareKey = value; } else if (key == G_Tag_View_Key) { diffChildren = 1; } attrs.push({ '@{~v#node.attrs.key}': key, '@{~v#node.attrs.value}': value }); amap[key] = value; }); currentParent['@{~v#node.force.diff.children}'] = currentParent['@{~v#node.force.diff.children}'] || diffChildren; unary = match[3] || G_Has(TO_VDOM_SELF_CLOSE, tag); if (DEBUG) { if (TO_VDOM_SELF_CLOSE[tag] && !match[3]) { console.error('avoid use tag:' + tag + ' without self close slash. near:' + match[0]); } } em = { '@{~v#node.outer.html}': chars, '@{~v#node.compare.key}': compareKey, '@{~v#node.tag}': tag, '@{~v#node.attrs}': attrs, '@{~v#node.attrs.map}': amap, '@{~v#node.children}': [], '@{~v#node.reused}': {}, '@{~v#node.start.pos}': current, '@{~v#node.self.close}': unary, '@{~v#content.start.pos}': current += moveLength = chars.length }; if (compareKey) { currentParent['@{~v#node.reused}'][compareKey] = 1; } currentParent['@{~v#node.children}'].push(em); if (!unary) { stack.push(em); if (DEBUG) { stack[stack.length - 1]['@{~v#tag.start.pos}'] = current - match[0].length; } currentParent = em; } chars = 0; } } } if (chars) { index = html.indexOf('<'); if (index < 0) { text = html; } else { text = html.substring(0, index); } current += moveLength = text.length; em = { '@{~v#node.tag}': V_TEXT_NODE, //'@{~v#node.html}': text, '@{~v#node.outer.html}': text }; currentParent['@{~v#node.children}'].push(em); } if (last == current) { if (DEBUG) { throw new Error('bad input:' + html); } break; } //substring is fater than slice . lower gc html = html.substring(moveLength); last = current; } if (DEBUG && stack.length > 1) { throw new Error('parsing failure:' + input); } return currentParent; };