一、vue3.0相比vue2有哪些升级?
1.重写虚拟DOM (Virtual DOM Rewrite)
vue3.0将 vdom 更新性能由与模版整体大小相关提升为与动态内容的数量相关
2.优化插槽生成(Optimized Slots Generation)
在当前的 Vue 版本中,当父组件重新渲染时,其子组件也必须重新渲染。 使用 Vue 3 ,可以单独重新渲染父组件和子组件。
3.静态树提升(Static Tree Hoisting)
使用静态树提升,这意味着 Vue 3 的编译器将能够检测到什么是静态组件,然后将其提升,从而降低了渲染成本。它将能够跳过未整个树结构打补丁的过程。
4.静态属性提升(Static Props Hoisting)
Vue 3 将跳过不会改变节点的打补丁过程。
5.基于 Proxy 的观察者机制
Object.defineProperty是一个相对比较昂贵的操作,因为它直接操作对象的属性,颗粒度比较小。将它替换为es6的Proxy,在目标对象之上架了一层拦截,代理的是对象而不是对象的属性。这样可以将原本对对象属性的操作变为对整个对象的操作,颗粒度变大。
javascript引擎在解析的时候希望对象的结构越稳定越好,如果对象一直在变,可优化性降低,proxy不需要对原始对象做太多操作。
6.使 Vue 更小(Tree Shaking)
Vue已经非常小了,在运行时(runtime)压缩后大约 20kb 。 但我们可以期待它会变得更加小,新的核心运行时压缩后大概 10kb 。 这将在很大程度上通过消除不使用的库(也称为Tree Shaking)来实现。 例如,如果您没有使用 过渡(transition)元素,则不会包含它。
Proxy只会代理对象的第一层,那么Vue3又是怎么处理这个问题的呢?
判断当前Reflect.get的返回值是否为Object,如果是则再通过reactive方法做代理。这样就实现了深度观测。
Proxy 与 Reflect?
Proxy 与 Reflect 是 ES6 为了操作对象引入的 API 。
Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。
Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。
Proxy
一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象, handler 是一个对象,声明了代理 target 的指定行为。
Reflect
ES6 中将 Object 的一些明显属于语言内部的方法移植到了 Reflect 对象上(当前某些方法会同时存在于 Object 和 Reflect 对象上),未来的新方法会只部署在 Reflect 对象上。
Reflect 对象对某些方法的返回结果进行了修改,使其更合理。
Reflect 对象使用函数的方式实现了 Object 的命令式操作。
2.diff算法
vue3.0中增加了静态标记,对静态元素做静态提升,不会比较,直接复用
3.TreeShaking
打包时清除多余代码,减少程序体积,更快
4.vue3.0的composition Api和vue2的Options Api?
Options Api:选项式API
composition Api:组合式API,逻辑组织,逻辑复用更容易;对TreeShaking友好;见不到this的使用,减少this指向不明的情况;
二、vue3中的hook函数,生命周期
hook
什么是hook
- 本质是一个函数,把setup函数中使用的composition API进行了封装,简而言之就是你在setup函数用能用的hook都能用
- 类似于Vue2中的mixin,就是拆分版的mixin,将导入操作交给开发者,mixin是根据对应的options Api直接merge到组件了
- 其优势,复用代码,让setup中的逻辑更清楚易懂
Vue 官方给出的自定义 Hook
的例子
import { ref, onMounted, onUnmounted } from "vue";
export function useMousePosition() {
const x = ref(0);
const y = ref(0);
function update(e) {
x.value = e.pageX;
y.value = e.pageY;
}
onMounted(() => {
window.addEventListener("mousemove", update);
});
onUnmounted(() => {
window.removeEventListener("mousemove", update);
});
return { x, y };
}
组件中使用:
import { useMousePosition } from "./mouse";
export default {
setup() {
const { x, y } = useMousePosition();
return { x, y };
},
};
vue3中的生命周期
// 导入生命周期组合式api,除了beforeCreate和created这两个生命周期函数没有组合式api
// 其他的生命周期函,都有对应的组合式api,命名方式只是在原有方法名的前面加上on
// setup()函数在这里充当了beforeCreate和created这两个生命周期函数的功能。
import { ref, onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount,onUnmounted } from "vue";
//注意:setup是在beforeCreate和created之前运行的。
//所以,在setup里面,无法调用data和methods里面的数据。
三、Typescript
Typescript与Js相比,有啥区别?
- 基本数据类型不同
js: boolean类型、number类型、string类型、array类型、nudefined、null
ts: 除了上面的类型外,还包含tuple类型(元组类型)、enum类型(枚举类型)、any类型(任意类型) - js 动态类型,运行运行时明确变量的类型,变量的类型由变量的值决定,并跟随值的改变而改变;ts 静态类型,声明时确定类型,之后不允许修改
- js 直接运行在浏览器和node.js环境中;ts 编译运行,始终先编译成JavaScript在运行
- js 弱类型,数据类型可以被忽略的语言。一个变量可以赋不同数据类型的值;ts 强类型,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了;
- ts增加的语法:
(1)静态类型:有利于检查代码错误,运行前检查类型错误
(2)函数缺省参数值
(3)class类
(4)模块:可以把声明、数据、函数和类封装在模块中
(5)接口
(6)类型注解:通过类型注解来增加编译时静态类型检查
类型注解和编译时类型检查有哪些?
string number
//数组类型 let names: string[]
//任意类型 let foo:any
//any类型也可用于数组 let list: any[]
//函数中使用类型 function greeting(person: string): string { return 'Hello, ' + person; }
//void类型,常用于没有返回值的函数 function warnUser(): void { alert("This is my warning message"); }
必填参:参数一旦声明,就要求传递,且类型需符合
可选参数:参数名后面加上问号,变成可选参数
function greeting(person: string, msg?: string): string { return "Hello, " + person; }
类?
class MyComp {
private _foo: string; // 私有属性,不能在类的外部访问
protected bar: string;// 保护属性,可以在子类中访问
// 构造函数参数加修饰符,能够定义为成员属性
constructor(public tua = "tua") {}
// 方法也有修饰符
private someMethod() {}
// 存取器:属性方式访问,可添加额外逻辑,控制读写性
get foo() { return this._foo }
set foo(val) { this._foo = val }
}
接口?
接口仅约束结构,不要求实现,使用更简单
interface Person {
firstName: string;
lastName: string;
}
function greeting(person: Person) {
return 'Hello, ' + person.firstName + ' ' + person.lastName;
}
const user = {firstName: 'Jane', lastName: 'User'};
console.log(user);
console.log(greeting(user));
四,vue3的项目在编写过程中和vue2有啥不同?
比如如何实现vue2里的this以及this暴露出一些方法(this.$forceUpdate
, this.$emit
)?
第一种:
<template>
<div ref="divRef">我是节点</div>
</template>
<script>
setup() {
const divRef= ref(null)
onMounted(() => { // 需要在DOM加载完毕之后才可获取到
console.log(divRef.value)
})
return { divRef }
},
</script>
比如表单重置时,就可以使用divRef.value.resetFields();
第二种:
import { getCurrentInstance } from 'vue'
const { proxy } = getCurrentInstance()
proxy.$parent
proxy.$refs
proxy.$nextTick
proxy.$attrs
proxy.$data
proxy.$el
proxy.$emit
proxy.$forceUpdate
proxy.$options
proxy.$props
proxy.$root
proxy.$slots
proxy.$watch
再找到this:
const _this= proxy.appContext.config.globalProperties
这里的_this就相当于vue2里的this
同理在Vue 3.x 设置全局属性/方法:
const app = createApp({})
app.config.globalProperties.foo = 'bar'
app.config.globalProperties.$http = () => {}
组件里使用
import { getCurrentInstance } from 'vue'
const MyComponent = {
setup() {
const internalInstance = getCurrentInstance()
// 访问 globalProperties
console.log(internalInstance.appContext.config.globalProperties)
}
}