目前公司项目都是vue2,其实真要把公司项目从vue2升级到vue3成本还是挺大的,尤其是公司内部在用的管理后台。后面想着如果有新项目就开始用vue3进行开发。
本篇主要总结一下:组合式api、响应式数据、计算属性、监听、ref、生命周期。
Vue CLI 是官方提供的基于 Webpack 的 Vue 工具链,它现在处于维护模式。我们建议使用 Vite 开始新的项目,除非你依赖特定的 Webpack 的特性。
具体详细介绍vite到这篇文章——vite学习指南
options Api 和 composition Api
Vue 2 使用的是选项式 API,而 Vue 3 引入了组合式 API
虽然 Vue 3 推荐使用组合式 API,但它仍然完全支持 Vue 2 的选项式 API,以保持向下兼容性。所以在 Vue 3 中,你可以自由选择使用选项式 API 或组合式 API 来编写你的组件逻辑。
选项式API有一个缺点:新增一个功能,需要分别在 data、methods、computed、watch等选项中修改代码,如果代码上千,修改或抽取封装这部分功能,有困难。
setup
setup 函数是组合式 API 的入口,用于组合组件的逻辑和功能。
<template>
<div>
<p>num: {{ num }}</p>
<p><button @click="addfn">num+1</button></p>
</div>
</template>
<script>
//vue2中会这样写
export default {
name: 'App',
data() {
return {
num: 0,
}
},
methods: {
addfn() {
this.num += 1;
}
}
}
//vue3中这样写
export default {
name: 'App',
setup() {
let num= 0;
function addfn(){
num += 1;
}
// 将数据和方法都交出去
return {num, addfn}
}
}
</script>
对比一下简单理解就是把vue2 data 和 methods 两个配置去除,改成 setup 就完成了 vue3 示例的重构
setup 是一个方法,平时如何定义变量和方法,这里就怎么写,最后将方法和变量都交出去。
这里其实还有一个问题,点击事件 num在界面没变,但方法却执行了。这是因为 num 变量不是响应式的。
现在我们先说 setup,后面在聊响应式的东西。这里要修复可以使用 ref(这个 ref 和 vue2 中指向元素或组件的ref,不是同一个东西):
<script>
import {ref} from 'vue'
export default {
name: 'App',
setup() {
let num= ref(0)
function addfn(){
num.value = +=1;
}
// 将数据和方法都交出去
return {num, addfn}
}
}
</script>
另外 setup 中的 this 是undefined,vue3 开始弱化 this。
最后说一下 setup 执行时机,比 beforeCreat 还早:
beforeCreate() {
console.log(1);
},
setup() {
console.log(2);
}
//先输出 2 再输出 1
setup语法糖
//方式1
setup() {
let num = ref(0);
function addfn() {
num .value +=1;
}
// 将数据和方法都交出去
return { num , addfn };
},
//方式2
<script setup>
// 属性和方法自动交出去
let num = ref(0);
function addfn() {
num.value +=1;
}
</script>
响应式数据
vue2 中放在 data 中的数据都是响应式的,在vue3 中可以通过 ref和reactive 两种方式来处理响应式。
<template>
<div>
<!-- 不能写 date.value,这里自动会给 value -->
<p>ref方式绑定响应式数据</p>
<p>num: {{ num }}</p>
<p><button @click="addfn">num+1</button></p>
<p>reactive方式绑定响应式数据</p>
<p>person.num: {{ person.num }}</p>
<p><button @click="addfnReactive">person.num+1</button></p>
</div>
</template>
<script setup>
import { ref,reactive } from "vue";
// 通过ref包裹后,类型变成 RefImpl。需要通过 .value 来访问和修改实际的值。 let num = ref(0); // 使用 ref 创建变量时,实际上你得到的是一个包含了值的对象,而不是直接的值。因此,在修改这个变量时,你需要通过 .value 来访问和修改实际的值,这样 Vue 才能够正确地追踪变化并进行响应。 // 使用 ref 创建的变量必须通过 .value 来访问和修改其值,这是为了确保 Vue 能够正确捕捉变化并更新视图。 function addfn() { // 通过 value 修改响应式数据。 num.value += 1; } // 通过 reactive 封装后的对象类型变成 Proxy。 const person = reactive({ num: 0 }) function addfnReactive() { person.num += 1; } </script>
ref vs reactive
1、宏观:
- ref 能定义基本类型和对象的响应式数据
- reactive 只能用于对象
写代码时还得记着是 ref 类型,需要增加 .value,好麻烦。这里安利一个 vscode 插件:
vscode 直接安装 Vue - Official(vscode 提示 TypeScript Vue Plugin (Volar) 已弃用,使用 Vue - Official 替代)
通过 vscode 设置,勾选 Auto-complete Ref value with .value,并设置 Applies to all profiles
2、使用场景
reactive 重新分配一个对象,会失去响应式(可使用 Object.assign 整体替换)
由于这些限制,我们建议使用 ref() 作为声明响应式状态的主要 API —— 官网 - reactive 局限性
个人习惯:
- 需要一个基本类型的响应式数据,只可使用 ref
- 对象使用 reactive
- 如果是表单,使用 ref 会出现很多 .value,不好看
toRefs
将一个响应式对象转换为一个普通对象,这个普通对象的每个属性都是指向源对象相应属性的 ref。每个单独的 ref 都是使用 toRef() 创建的。
不明白请看下面代码。
<template>
<section>
<p>name: {{ person.name }}</p>
<p>age: {{ person.age }}</p>
<p><button @click="changeAge">change age</button></p>
</section>
</template>
<script setup>
import { ref, reactive, toRefs } from "vue";
let person = reactive({
name: "dami",
age: 18,
})
//从响应式对象中解构出 age,然后通过方法修改 age 的值,发现页面没更新:
let {age} = person;
function changeAge () {
age+=1;
}
//这是因为解构出的 age 不在是响应式。可以使用 toRefs,就像这样 这样age就变成了响应式
let {age} = toRefs(person);
function changeAge () {
age.value+=1;
}
</script>
计算属性
//vue2中这样写
computed: {
now: function () {
return Date.now();
}
}
//vue3中这样写
let now = computed(() => {
return Date.now()
})
watch
vue3 中说 watch 只能监视4种数据:
- ref定义的数据
- reactive 定义的数据
- 函数返回一个值(getter函数)
- 一个包含上述内容的数组
<template>
<section>
<p>age: {{ age}}</p>
<p><button @click="age += 1">change age</button></p>
<p><button @click="stopWatch">停止监听 age 变化</button></p>
</section>
</template>
<script setup>
import { ref, watch } from "vue";
let age = ref(18)
let stopWatch = watch(age, (newValue, oldValue) => {
console.log('年龄从', oldValue, '变为', newValue);
});
</script>
- watch 监视的ref变量,无需增加
.value。安装好vscode 插件,在这种情况下也不会自动给你加 .value。 - watch 返回一个函数,执行后将解除监视。就像 vue2 中的 vm.$watch 方法,返回 unwatch。
监视对象中的属性
前面我们监视的都是整个对象,比如现在要监视对象中的某个属性。这里分为基本类型和对象类型。
// reactive 和 ref 都可以用如下形式
// 利用 getter。如果需要则增加 deep
watch(() => person.car, (new, old) => {
console.log(new)
}, {deep: true})
生命周期
使用步骤
- 先从vue中导入以
on打头的生命周期钩子函数 - 在setup函数中调用生命周期函数并传入回调函数
- 生命周期钩子函数可以调用多次
<template>
<div>生命周期函数</div>
</template>
<script>
import { onMounted } from 'vue'
export default {
setup() {
// 时机成熟 回调函数自动执行
onMounted(() => {
console.log('mouted生命周期执行了')
})
onMounted(() => {
console.log('mouted生命周期函数又执行了')
})
}
}
</script>

非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/index.php/2022/03/18/vue3%e5%85%a5%e9%97%a8-%e5%9f%ba%e7%a1%80%e7%af%87/