1.模板引擎 (性能差 )需要正则匹配替换 1.0的时候没有引入虚拟Dom的改变
2.采用虚拟DOm ,数据变化后比较虚拟dom差异,最后更新需要更新的地方
3.核心就是我们需要将,模板变成我们的js语法,通过js语法去生成虚拟dom
从一个东西,变成另一个东西 语法之间的转化 es6-> es5
从css压缩 我们需要先变成语法树在重新组装代码成为新的语法,将template语法转换成render函数
模板:
<body>
<div id="app">
<div>
{{name}}
</div>
<span>{{age}}</span>
</div>
<script src="vue.js"></script>
<script>
//响应式的数据,数据变化了我可以监控数据
const vm = new Vue({
//代理数据
data: {
name: 'bozi',
age: 18,
adress: {
number: 30,
content: '西安'
},
hobby: ['eat', 'drink', { a: 1 }]
},
template: `<div>hello</div>`
// el:'#app', //我们要将数据 解析到el元素上
});
vm.$mount('#app')
手动实现挂载,并先进行查找有没有render函数,没有render看一下是否写了template,没写template采用外部的template,判断有没有模板
export function initMixin (Vue) {//给vue上增加init方法
Vue.prototype._init = function (options) {//用于初始化操作
const vm = this
vm.$options = options
//初始化状态
initstate(vm)
if (options.el) {
vm.$mount(options.el);//实现数据的挂载
}
}
Vue.prototype.$mount = function (el) {
const vm = this;
el= document.querySelector(el);
let ops = vm.$options
if (!ops.render) {//先进行查找有没有render函数
let template;//没有render看一下是否写了template,
//没写template采用外部的template
if (!ops.template && el) {//没有模板 但是写了el
template = el.outerHTML
} else {
if (el) {
template = ops.template
}
}
console.log(template);
//写了template 就用 写了template
// console.log(template);
if(template) {
//有模板就需要进行编译
const render = compileToFunction(template);
ops.render = render //jx 最终会被编译成h('XXX')
}
}
ops.render ;//最终就可以获取render方法
//script 标签引用的vue.global.js 这个编译过程是在浏览器运行的
//runtime是不包含编译的,整个编译是打包的时候通过loader来转义.vue文件的runtime的时候不能使用tempate
}
对模板进行编译处理
const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`;
const qnameCapture = `((?:${ncname}\\:)?${ncname})`;
const starTagOpen = new RegExp(`^<${qnameCapture}`); //他匹配到的分组是一个标签名 <xxx 匹配到的是开始 标签的名字
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*`); //他匹配到的是 </xxx 最终匹配到的是结束标签的名字
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>']+)))?/; //匹配属性
//第一个分组就是属性key value 就是 分组3/分组4/分组5
const starTagClose = /^\s*(\/?)>/;
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g //{{asdsads}} //匹配到的内容就是我们表达式的变量
//vue3采用的不是正则
//对模板进行编译处理
function parseHTML (html) {
function start(tag,attrs) {
console.log(tag,attrs,'开始');
}
function chars(text) {
console.log(text,'文本');
}
function end(tag) {
console.log(tag,'结束');
}
function advnce (n) {
html.substring(n);
}
function parseStarTag () {
const start = html.match(starTagOpen);
if (start) {
const match = {
tagName: start[1],//标签名
attr: []
}
advnce(start[0].length);
let attr, end
while (!(end = html.match(starTagClose)) && (attr = html.match(attribute))) {
advnce(attr[0].length)
match.attrs.push({ name: attr[1], value: attr[3] || attr[4] || attr[5] })
}
if (end) {
advnce(end[0].length)
}
return match
}
return false; //不是开始标签
}
while (html) {//zhtml最开始是一个<di>hello</div>
//如果textend为0说明是一个开始标签或者结束标签
//如果textend > 0 说明就是文本结束的位置
let textEnd = html.indexOf('<'); //如果indexof中的索引是0,则说明是个标签
if ( textEnd== 0) {
const startTagMatch = parseStarTag();//开始标签的结果
start(startTagMatch,tagName,startTagMatch.attrs)
if (startTagMatch) {//解析到的开始标签
continue
}
let endTagMatch = html.match(endTag);
if (endTagMatch) {
advnce(endTagMatch[0].length);
end(endTagMatch[1])
continue
}
html.match(endTag)
}
if (textEnd >0) {
let text = html.substring(0, textEnd);//文本内容
if (text) {
advnce(text.length);//解析到的文本
chars()
}
}
}
console.log(html);
}
export function compileToFunction (template) {
//1.就是将template 转化成ast语法树
let ast = parseHTML(template);
//2.生成render方法,(render)方法执行后的返回结果就是 虚拟dom
}