vue3的template
支持不用根标签包裹
减少便签层级,减少内存占用。
<template>
12
</template>
能在页面中渲染,不报错
router写法不一样
在vue3中,定义了一个vue-router
然后引入的useRoute
,useRouter
相当于vue2的 this.$route
,this.$router
, 但是其他之前vue2的操作都可以进行。
比如进行跳转不是用this.$router.push('/about')
,而是useRouter().push('/about')
import {useRouter,useRoute} from "vue-router";
setup(){
const router= useRouter()
const route= useRoute()
function jump(){
router.push('/about')
}
onMounted(()=>{
let path = route.path
let query = route.query
})
return{
jump
}
}
全局API写法不一样
2.x 全局 API(Vue ) | 3.x 实例 API (app ) |
---|---|
Vue.config.xxxx | app.config.xxxx |
Vue.config.productionTip | 移除 |
Vue.component | app.component |
Vue.directive | app.directive |
Vue.mixin | app.mixin |
Vue.use | app.use |
Vue.prototype | app.config.globalProperties |
钩子函数写法不一样
选项式 API | Hook inside setup |
---|---|
beforeCreate | Not needed* |
created | Not needed* |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeUnmount | onBeforeUnmount |
unmounted | onUnmounted |
errorCaptured | onErrorCaptured |
renderTracked | onRenderTracked |
renderTriggered | onRenderTriggered |
activated | onActivated |
deactivated | onDeactivated |
生命周期原理不一样,借用图片:
在vue2中,我们是先new Vue()
,然后执行beforeCreate
与created
接着问你有没有vm.$mount(el)
,有,才继续执行,但是在vue3中,它是先全部准备好后然后再进行函数。
其实在vue3中生命周期没有多大的改变,只是改变了改变了销毁前,和销毁,让它更加语义化了 beforeDestroy
改名为beforeUnmount
,destroyed
改名为unmounted
移除vue2的一些写法
-
移除keyCode作为 v-on 的修饰符,同时也不再支持
config.keyCodes
-
移除
v-on.native
修饰符 -
移除过滤器(
filter
)
vue3新增Teleport标签
teleport
提供了一种有趣的方法,允许我们控制在 DOM 中哪个父节点下渲染了 HTML,而不必求助于全局状态或将其拆分为两个组件。
其实就是可以不考虑你写在什么位置,你可以定义teleport
在任意标签里进行定位等(常见操作为模态框),除了body外,还可以写css选择器(id,class
)
// 在同一目标上使用多个 teleport
<teleport to="#modals">
<div>A</div>
</teleport>
<teleport to="#modals">
<div>B</div>
</teleport>
<!-- result-->
<div id="modals">
<div>A</div>
<div>B</div>
</div>
具体可参考:teleport
vue3 watch可以监听多个属性
响应式原理不一样
可参考精品文章:vue3 的响应式和以前有什么区别,Proxy 无敌?
Proxy 和 Reflect - 掘金 (juejin.cn)
Proxy
功能强大得多,因为它将所有东西转发到目标对象。
Proxy中apply的作用:
function delay(f, ms) {
return new Proxy(f, {
apply(target, thisArg, args) {
setTimeout(() => target.apply(thisArg, args), ms);
}
});
}
function sayHi(user) {
alert(`Hello, ${user}!`);
}
sayHi = delay(sayHi, 3000);
alert(sayHi.length); // 1 (*) proxy 转发“获取 length” 操作到目标对象
sayHi("John"); // Hello, John! (3秒后)
解释为什么要用Reflect,它的receiver参数可以读取属性所在的this指向
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) {
return target[prop]; // (*) target = user
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
// Expected: Admin
alert(admin.name); // 输出:Guest (?!?)
为了解决这种情况,我们需要 get
钩子的第三个参数 receiver
。它保证传递正确的 this
给 getter。在我们的情况下是 admin
。
如何为 getter 传递上下文?对于常规函数,我们可以使用 call/apply
,但这是一个 getter,它不是“被调用”的,只是被访问的。
Reflect.get
可以做到的。如果我们使用它,一切都会正常运行。
这是更正后的变体:
let user = {
_name: "Guest",
get name() {
return this._name;
}
};
let userProxy = new Proxy(user, {
get(target, prop, receiver) { // receiver = admin
return Reflect.get(target, prop, receiver); // (*)
}
});
let admin = {
__proto__: userProxy,
_name: "Admin"
};
alert(admin.name); // Admin
现在 receiver
,保留了对正确 this
的引用(即admin
)的引用,该引用将在 (*)
行中使用Reflect.get
传递给getter。
Map
, Set
, Date
, Promise
需要借助于Reflect完成代理
diff算法不一样
可精读我的另一篇:react+vue2+vue3 diff算法分析及比较
打包优化
vue3 中针对全局 和内部的API进行了重构,并考虑到tree-shaking
的支持。因此,全局 API 现在只能作为ES模块构建的命名导出进行访问。
mp.weixin.qq.com/s/PdG6YYi4_…
静态标记
diff算法不比较静态标签