一、Vue3优点
1.类型支持更好:
- vue2中使用new Vue的方式会产生动态的东西,像this
- 使用函数的方式,函数方式减少this的使用,有益于对ts的支持
2.利于tree-shaking:
- vue2中很多组件与vue实例连在一起,即便没有使用,还是会被打包,没法优化
- vue3中通过命名导出导入其中的大多数 API,以便打包器可以检测出未使用的代码并删除它们
3.API简化、一致性:render函数、sync修饰符,指令定义等
4.复用性:composition API
5.性能优化:响应式、编译优化
6.扩展性:自定义渲染器
二、vue3初始化
vue3初始化用法:
-
<!DOCTYPE html>
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8" />
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
-
<title>Document
</title>
-
</head>
-
<body>
-
<div id="app">
-
<h3>{{ title }}
</h3>
-
</div>
-
<script src="http://unpkg.com/vue@next">
</script>
-
<script>
-
const { createApp } = Vue;
-
const app = createApp({
-
data() {
-
return {
-
title:
"hello"
-
};
-
}
-
});
-
-
app.mount(
"#app");
-
</script>
-
</body>
-
</html>
三、手写vue3初始化代码
整体思路:
从上面的初始化代码可看出,要有以下几点:
1.createApp:从vue中导出createApp
2.mount:createApp()返回包含mount的对象
-
const Vue = {
-
createApp(options) {
-
return {
-
mount(selector) {
-
-
}
-
};
-
}
-
};
mount中会获取渲染函数,渲染DOM元素,并追加到宿主元素
3.compile:返回render函数
4.render:返回DOM元素
-
const Vue = {
-
createApp(options) {
-
return {
-
mount(selector) {
-
const parent =
document.querySelector(selector);
-
// 获取渲染函数:模板=>渲染函数render
-
if (options.render) {
-
options.render =
this.compile(parent.innerHTML);
-
}
-
// 渲染DOM,追加到宿主元素
-
const el = options.render.call(options.data());
-
parent.innerHTML =
"";
-
parent.appendChild(el);
-
},
-
// 将模板转化为渲染函数
-
compile(template) {
-
return
function render() {
-
// 描述视图
-
// 假设返回h3
-
const h3 =
document.createElement(
"h3");
-
h3.textContent =
this.title;
-
return h3;
-
};
-
}
-
};
-
}
-
};
5.兼容composion API:用Proxy对属性进行监听,当setup中有该属性时,获取setup中的值,没有时再去data、methods等中查找
-
<!DOCTYPE html>
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8" />
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
-
<title>Document
</title>
-
</head>
-
<body>
-
<div id="app">
-
<h3>{{ title }}
</h3>
-
</div>
-
<!-- <script src="http://unpkg.com/vue@next"></script> -->
-
<script>
-
const Vue = {
-
createApp(options) {
-
return {
-
mount(selector) {
-
const parent =
document.querySelector(selector);
-
// 获取渲染函数:模板=>渲染函数render
-
if (!options.render) {
-
options.render =
this.compile(parent.innerHTML);
-
console.log(options.render);
-
}
-
-
// 将setup和data中的数据分别保存到app实例上,以便后面使用
-
if (options.setup) {
-
this.setupState = options.setup();
-
}
else {
-
this.data = options.data();
-
}
-
// 兼容composition API
-
this.proxy =
new
Proxy(
this, {
-
get(target, key) {
-
if (key
in target.setupState) {
-
return target.setupState[key];
-
}
-
return target.data[key];
-
},
-
set(target, key, val) {
-
if (key
in target.setupState) {
-
target.setupState[key] = val;
-
}
else {
-
target.data[key] = val;
-
}
-
}
-
});
-
-
// 渲染DOM,追加到宿主元素
-
const el = options.render.call(
this.proxy);
-
parent.innerHTML =
"";
-
parent.appendChild(el);
-
},
-
// 将模板转化为渲染函数
-
compile(template) {
-
return
function render() {
-
// console.log(this); //call绑定后this指向绑定的数据
-
// 描述视图
-
const h3 =
document.createElement(
"h3");
-
h3.textContent =
this.title;
-
return h3;
-
};
-
}
-
};
-
}
-
};
-
</script>
-
<script>
-
const { createApp } = Vue;
-
const app = createApp({
-
data() {
-
return {
-
title:
"hello"
-
};
-
},
-
setup() {
-
return {
-
title:
"setup title"
-
};
-
}
-
});
-
-
app.mount(
"#app");
-
</script>
-
</body>
-
</html>
6.createRenderer:渲染器,针对不同的平台环境,有不同的代码,增加代码的扩展性。
浏览器环境:设置一个通用的渲染器,将需要用到的dom操作作为参数传进去
-
<!DOCTYPE html>
-
<html lang="en">
-
<head>
-
<meta charset="UTF-8" />
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
-
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
-
<title>Document
</title>
-
</head>
-
<body>
-
<div id="app">
-
<h3>{{ title }}
</h3>
-
</div>
-
<!-- <script src="http://unpkg.com/vue@next"></script> -->
-
<script>
-
const Vue = {
-
createApp(options) {
-
const renderer = Vue.createRenderer({
-
querySelector(selector) {
-
return
document.querySelector(selector);
-
},
-
insert(child, parent, anchor) {
-
parent.insertBefore(child, anchor ||
null);
-
}
-
});
-
return renderer.createApp(options);
-
},
-
createRenderer({ querySelector, insert }) {
-
// 获得渲染器
-
return {
-
createApp(options) {
-
return {
-
mount(selector) {
-
const parent = querySelector(selector);
-
// 获取渲染函数:模板=>渲染函数render
-
if (!options.render) {
-
options.render =
this.compile(parent.innerHTML);
-
console.log(options.render);
-
}
-
-
// 将setup和data中的数据分别保存到app实例上,以便后面使用
-
if (options.setup) {
-
this.setupState = options.setup();
-
}
else {
-
this.data = options.data();
-
}
-
// 兼容composition API
-
this.proxy =
new
Proxy(
this, {
-
get(target, key) {
-
if (key
in target.setupState) {
-
return target.setupState[key];
-
}
-
return target.data[key];
-
},
-
set(target, key, val) {
-
if (key
in target.setupState) {
-
target.setupState[key] = val;
-
}
else {
-
target.data[key] = val;
-
}
-
}
-
});
-
-
// 渲染DOM,追加到宿主元素
-
const el = options.render.call(
this.proxy);
-
parent.innerHTML =
"";
-
insert(el, parent);
-
},
-
// 将模板转化为渲染函数
-
compile(template) {
-
return
function render() {
-
// console.log(this); //call绑定后this指向绑定的数据
-
// 描述视图
-
const h3 =
document.createElement(
"h3");
-
h3.textContent =
this.title;
-
return h3;
-
};
-
}
-
};
-
}
-
};
-
}
-
};
-
</script>
-
<script>
-
const { createApp } = Vue;
-
const app = createApp({
-
data() {
-
return {
-
title:
"hello"
-
};
-
},
-
setup() {
-
return {
-
title:
"setup title"
-
};
-
}
-
});
-
-
app.mount(
"#app");
-
</script>
-
</body>
-
</html>
四、总结
vue3初始化中做了什么:
- vue3中初始化时设置了一个渲染器,返回createApp方法
- createApp方法返回一个mount方法
- mount方法里对composition API做兼容处理,获取渲染函数,渲染DOM并追加到宿主元素
- 初始化时调用的createApp中,获取设置好的渲染器并传入渲染参数,返回渲染器中的createApp方法
转载:https://blog.csdn.net/MiemieWan/article/details/117220491
查看评论