1、编译阶段优化:VUE2每个组件实例都对应一个watcher实例,watcher实例会在组件渲染的过程中,把用到的数据property记录为依赖,当依赖发生变化触发setter通知到watcher从而使关联的组件重新渲染;
VUE3在编译阶段做了进一步优化:
1. diff算法中相比VUE2增加了静态标记,给发生变化的地方添加一个flag标记,下次发生变化的时候直接找到这个flag进行比较
2.静态提升(vue3对不参与更新的元素做了静态提升,他们只会被创建一次在渲染的时候直接复用,免去重复创
建,元素会被打上静态标记值-1,特殊标志是负整数,表示永远不会用于diff,VUE2时未参与更新的元素也在
render函数中,会重复创建阶段;)
3.事件监听缓存(默认情况下绑定事件行为,会被视为动态绑定【没开启事件监听器缓存】,所以每次都要追踪他的变化;开始事件侦听器缓存后,没有了静态标记,下次diff算法的时候直接用)
4.SSR优化:(在静态内容大到一定量级的时候,会使用createStaticVNode方法,
在客户端生成一staticNode,这些静态node会被直接innerHtml进去,就不需要创建对象再根据对象渲染)
2、源码体积更小:除了移除一些不常用的API,最重要的是treeshanking任何一个函数(如:ref、reavtived、conputed等)仅在用到时才打包,打包的整体体积更小
3、响应式系统:vue2采用defineproperty来劫持整个对象,然后深度遍历所有属性,给每个属性添加getter和setter实现响应式;vue3采用proxy重写了响应式系统,proxy可以对整个对象进行代理,所以不需要深度遍历,下面是一个代理的例子:
//定义一个静态方法来实现接口与实现类的直接检验
//静态方法不要写出Interface.prototype ,因为这是写到接口的原型链上的
//我们要把静态的函数直接写到类层次上
//定义一个接口类
var Interface = function (name, methods) {//name:接口名字
if(arguments.length < 2){
alert('必须是两个参数')
}
this.name = name;
this.methods = [];//定义一个空数组装载函数名
for(var i=0; i<methods.length; i++) {
if(typeof methods[i] != 'string') {
alert('函数名必须是字符串类型')
} else {
this.methods.push(methods[i]);
}
}
};
//我们要把静态的函数直接写到类层次上
Interface.ensureImplement = function (object) {
if (arguments.length < 2) {
throw new Error("参数必须不少于2个");
return false;
}
for(var i=0; i<arguments.length; i++){
var inter = arguments[i];
//如果是接口就必须是Interface类型
if(inter.constructor !== Interface) {
throw new Error("如果是接口类的话,就必须是Interface类型");
}
//判断接口中的方法是否全部实现
//遍历函数集合分析
for(var j=0; j<inter.methods.length; j++) {
var method = inter.methods[j];//接口中所有函数
//object[method]传入的函数
//最终是判断传入的函数是否与接口中所用函数匹配
if(!object[method] || typeof object[method] != 'function'){
//实现类中必须有方法名字与接口中所用方法名相同
throw new Error('实现类中没有完全实现接口中的所有方法');
}
}
}
}
//图书类
/*
* bid 图书id
* bName 图书名称
* bPrice 图书价格
* */
var Book = function(bid,bName,bPrice) {
this.bid = bid;
this.bName = bName;
this.bPrice = bPrice;
}
//目标类
var myBookShop = (function (){
var books = {}; // 闭包
return function (bks) {
// 初始化
if (typeof bks === 'object') {
books = bks;
}
// 加书
this.addBook = function (book) {
books[book.id] = book;
}
// 找书
this.findBook = function (bid) {
if(books[bid]) {
return books[bid];
}else{
return null;
}
}
// 还书
this.returnBook = function (book) {
this.addBook(book);
}
// 借书
this.lendBook = function (bid) {
var book = this.findBook(bid);
return book;
}
}
})();
// 步骤三,普通代理
var myBookShopProxy = function (bks) {
var obj = new myBookShop(bks); // 类似于目标类的引用
// 加书
this.addBook = function (book) {
obj.addBook(book);
}
// 找书
this.findBook = function (bid) {
return obj.findBook(bid);
}
// 还书
this.returnBook = function (book) {
obj.returnBook(book);
}
// 借书
this.lendBook = function (bid) {
return obj.lendBook(bid);
}
}
//步骤四,添加数据后,开始访问
var proxy = new myBookShopProxy({
'001': new Book('001', 'extjs', '45'),
'002': new Book('002', 'js', '60')
});
console.log(proxy.lendBook('001').bName);