模板编译
- 渲染模板的时候需要一个方法用数据代替模板中的变量(方法:render)
- 先把模板变成一个render方法 reder(){return _l(3,_c(‘li’,name))}
- 需要去当前实例上取值 width
- 虚拟dom对象=》可描述dom结构 (diff算法)
- 生成真实dom扔到页面中
- 模板编译原理,AST语法树,先表示出html来=>js语法
- 先看实例化的时候有没有el选项,如果有就直接挂载,挂载的时候需要一个方法mount
Vue.prototype.$mount = function (el){
el = document.getElementById(el),
const vm = this
const options = vm.$options
vm.$options.el = el
if(!options.render){
let template = options.template
if(!template && el){
template = el.outerHTML
}
const render = compileToFunction(template)
options.render = render
}
}
接下来实现compileToFunction方法,用来将模板变成函数
1. vue中会通过一些正则表达式匹配template中的字符串
```js
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const dynamicArgAttribute = /^\s*((?:v-[\w-]+:|@|:|#)\[[^=]+?\][^\s"'<>\/=]*)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z${unicodeRegExp.source}]*`
const qnameCapture = `((?:${ncname}\\:)?${ncname})`
const startTagOpen = new RegExp(`^<${qnameCapture}`)
const startTagClose = /^\s*(\/?)>/
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`)
const doctype = /^<!DOCTYPE [^>]+>/i
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g;
```
function createASTElement(tag,attrs){
return {
tag,
type:1,
children:[],
attrs,
parent:null
}
}
let root = null;
let currentParent
let stack = []
function parseHTML(html){
function start(targName,attrs){
let element = createASTElement(targName,attrs)
if(!root){
root = element
}
currentParent = element
stack.push(element)
}
function end(tagName){
element = stack.pop()
currentParent = stack[stack.length-1]
if(currentParent){
element.parent = currentParent
currentParent.children.push(element)
}
}
function chars(text){
text = text.replace(/\s/g,'');
currentParent.children.push({
type:3,
text,
})
}
function advance(len){
html = html.substring(len)
}
function parseStartTag(){
const start = html.match(startTagOpen)
if(start){
let match = {
tagName:start[0],
attrs:[]
}
advance(start[0].length)