一,vue3的新变化
1,性能上
- 1,打包大小减少41%,
- 2,内存占用减少54%
- 3,初次渲染快55%,更新渲染快133%
2,新增了setup函数
setup执行的时机是在beforeCreate生命函数之前执行,只执行一次,因此在这个函数中是不能通过this来获取实例的
setup是一个函数,接受两个参数(props和context)
- props就是组件的props
- context
context:上下文对象,这个对象有三个属性;分别是:
- attrs:组件外部传递过来的,但没有在props配置中声明的属性,相当于捡漏
- slots:收到的插槽内容
- emit:分发自定义事件给父组件
3,新增了ref与reactive
ref和reactive一样,也是用来实现响应式数据的方法,ref底层其实还是reactive,所以当运行时系统会自动根据传入的ref转换成reactive.
区别:
- 1,ref用来定义基本数据类型;
- 2,reactive用来定义对象或者数组类型的数据
- 3,其实ref也能定义对象类型的数据,但是在vue的底层上会自动通过reactive转为代理对象
- 4,ref定义的响应式数据,操数据需要.value,而在模板读取中直接写变量名就行,不需要写.value,其实在vue底层,已经帮我们做了.value;
- 5,reactive定义的数据:操作与读取数据均不需要.value
let state =1与let state=ref(1);前者是对于简单的值类型进行声明,而后者加上了ref函数,就将该值类型的转换成了对象(引用对象);这一点至关重要,转换成对象之后,对象上有何很重要的属性就是value,他的值就是state的值为666,所以在vue2中想要读取某个变量身上的属性,我们需要加上一个.value
4,新增了两个生命周期钩子
将beforeDestroy改名为beforeUnmount,destroyed改名为unmounted,
5,响应式原理发生了变化
- 在vue2中,是通过Object.defineProperty()里面的set与get函数来实现响应式的,数据劫持其实就是vue的核心
- 在vue3中,是通过es6新增的代理对象Proxy来实现响应式的,也是利用是数据劫持,并通过reflect操作源对象内部的数据
6,新增了组合式API
组合式 API 是一系列 API 的集合,使我们可以使用函数而不是声明选项的方式书写 Vue 组件。它是一个概括性的术语,涵盖了以下方面的 API
- 响应性 API:例如ref()和reactive(),使我们可以直接创建响应式状态、计算属性和侦听器
- 生命周期钩子:例如onMounted()和onUnmounted(),使我们可以在组件各个生命周期阶段添加逻辑。
- 依赖注入:例如provide()和inject(),使我们可以在使用响应性 API 时,利用 Vue 的依赖注入系统
详情请见:组合式API
7,入口函数main.js
1,在vue2中,这里就是引入构造函数Vue,然后new Vue传入配置项就生成了vm实例
import Vue from "vue"
import App from "./App.vue"
import router from "./router"
import store from "./store"
new Vue({
router,
store,
render: h => h(App)
}).$mount("#app")
2,在vue3中,这里使用vue库的createApp方法传入基组件生成vm,然后再调用vm的mount方法传入选择器将实例挂载在dom节点上。
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
八,计算属性与监视
1,watchEffect函数
- watch:既要指明监视的属性,也要指明监视的回调。
- watchEffect:不用指明监视哪个属性,监视的回调中用到哪个属性,那就监视哪个属性
watchEffect跟computed类似,区别有:
- computed注重的计算出来的结果(回调函数的返回值),所以必须要return;
- 而watchEffect更注重的是过程(回调函数的函数体),所以不用return;
//情况一:监视ref定义的响应式数据
watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue)
},{immediate:true})
//情况二:监视多个ref定义的响应式数据
watch([sum,msg],(newValue,oldValue)=>{
console.log('sum或msg变化了',newValue,oldValue)
})
/* 情况三:监视reactive定义的响应式数据
若watch监视的是reactive定义的响应式数据,则无法正确获得oldValue!!
若watch监视的是reactive定义的响应式数据,则强制开启了深度监视
*/
watch(person,(newValue,oldValue)=>{
console.log('person变化了',newValue,oldValue)
},{immediate:true,deep:false}) //此处的deep配置不再奏效
//情况四:监视reactive定义的响应式数据中的某个属性
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//情况五:监视reactive定义的响应式数据中的某些属性
watch([()=>person.job,()=>person.name],(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{immediate:true,deep:true})
//特殊情况
watch(()=>person.job,(newValue,oldValue)=>{
console.log('person的job变化了',newValue,oldValue)
},{deep:true}) //此处由于监视的是reactive素定义的对象中的某个属性,所以deep配置有效
获取屏幕宽高
1,新建utils.js文件
import { ref, onMounted, onBeforeUnmount } from "vue";
//导出获取窗口的宽高
export function useWinSize() {
const size = ref({ width: window.innerWidth, height: window.innerHeight });
//窗口变化时候更新 size
function onResize() {
size.value = {
//用窗口的最新宽高更新 width 与 height
width: window.innerWidth,
height: window.innerHeight,
};
}
//组件 挂载完毕 更新 size
onMounted(() => {
window.addEventListener("resize", onResize);
});
//组件 要卸载的时候移除 事件监听
onBeforeUnmount(() => {
window.removeEventListener("resize", onResize);
});
return size;
}
2,在HomeView中使用
<template>
<div>
<h1>setup</h1>
<button @click="num++">{{ num }}</button>
<step-com :value="num" @input="num = $event" ref="stepper"></step-com>
<p>{{ size }}</p>
</div>
</template>
<script setup>
// 使用setup 可以简写 ,不用导出组件不用注册了
import StepCom from "@/components/StepCom.vue";
import { onMounted, ref } from "vue";
import { useWinSize } from "@/utils/utils";
const num = ref(5);
const stepper = ref();
onMounted(() => {
console.log("组件已经挂载完毕");
//组件挂在完毕引用stepper组件
/* stepper.value 就是对stepper-com组件的引用 */
console.log(stepper.value.count);
});
const size = useWinSize();
</script>
<style>
</style>
九,setup语法糖
只需要在 script 标签中添加 setup,组件只需引入不用注册,属性和方法也不用返回,setup 函数也不需要,甚至 export default 都不用写了,不仅是数据,计算属性和方法,甚至是自定义指令也可以在我们的 template 中自动获得。
setup script 语法糖提供了三个新的API来供我们使用:defineProps、defineEmit和useContext
- defineProps 用来接收父组件传来的值props
- defineEmit 用来声明触发的事件表。
- useContext 用来获取组件上下文context。