Vue3已经发布一年多了,不知道大家在日常开发中有没有用上Vue3呢,通过这篇文章让我们来看看Vue3和之前的版本有哪些不同吧:
1.Vue2.x的时候采用的是选项式API,而Vue3.x呢则采用了组合式 API.
什么是选项API写法:Options ApI
-
咱们在vue2.x项目中使用的就是
选项API
写法- 代码风格:data选项写数据,methods选项写函数…,一个功能逻辑的代码分散。
- 优点:易于学习和使用,写代码的位置已经约定好
- 缺点:代码组织性差,相似的逻辑(功能)代码不便于复用,逻辑复杂代码多了不好阅读。
什么是组合API:Composition API
- 以功能为单位组织代码结构,后续重用功能更加方便。
通过创建 Vue 组件,我们可以将界面中重复的部分连同其功能一起提取为可重用的代码段。仅此一项就可以使我们的应用在可维护性和灵活性方面走得相当远。然而,我们的经验已经证明,光靠这一点可能并不够,尤其是当你的应用变得非常大的时候——想想几百个组件。处理这样的大型应用时,共享和重用代码变得尤为重要。
使用 (data
、computed
、methods
、watch
) 组件选项来组织逻辑通常都很有效。然而,当我们的组件开始变得更大时,逻辑关注点的列表也会增长。尤其对于那些一开始没有编写这些组件的人来说,这会导致组件难以阅读和理解。
这是一个大型组件的示例,其中逻辑关注点按颜色进行分组。
这种碎片化使得理解和维护复杂组件变得困难。选项的分离掩盖了潜在的逻辑问题。此外,在处理单个逻辑关注点时,我们必须不断地“跳转”相关代码的选项块。
如果能够将同一个逻辑关注点相关代码收集在一起会更好。而这正是组合式 API 使我们能够做到的。
1.组合式 API 基础
那我们在哪里使用他呢?在 Vue 组件中,我们将此位置称为 setup
setup
组件选项
使用细节:
setup
是一个新的组件选项,作为组件中使用组合API的起点。- 从组件生命周期来看,它的执行在组件实例创建之前
vue2.x的beforeCreate
执行。 - 这就意味着在
setup
函数中this
还不是组件实例,this
此时是undefined
- 在模版中需要使用的数据和函数,需要在
setup
返回。
演示代码:
<template>
<div>
<div>setup函数用法</div>
<hr>
<div>{{msg}}</div>
<div>{{info}}</div>
<div>
<button @click='handleClick'>点击</button>
</div>
</div>
</template>
<script>
export default {
name: 'App',
// Vue3依然可以使用data中的数据,但是不建议使用(这是选项API)
data () {
return {
info: 'nihao'
}
},
setup () {
// 触发时机在beforCreate/created生命周期之前
// Vue3中beforCreate/created声明周期函数已经废弃了,其实已经被setup替代了
// 此时无法访问this,因为组件实例此时尚未创建
// console.log(this)
// 定义事件函数
const handleClick = () => {
console.log('click')
}
// 这里返回的数据用于给模板使用:类似于之前data中提供的数据
return {
msg: 'hello',
handleClick
}
}
}
</script>
<style lang="less">
</style>
复制代码
总结:
- setup选项是实现组合API的基础
- 触发的时机在beforeCreate之前
- Vue3中beforCreate/created声明周期函数已经废弃了,其实已经被setup替代了
- 此时无法访问this,因为组件实例此时尚未创建
- setup的返回值用于给模板提供数据和方法
- 模板依然可以从data获取数据,但是不建议使用data了。
2.组合API-生命周期
- 回顾vue2.x生命周期钩子函数:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
- 认识vue3.0生命周期钩子函数
setup
创建实例前onBeforeMount
挂载DOM前onMounted
挂载DOM后onBeforeUpdate
更新组件前onUpdated
更新组件后onBeforeUnmount
卸载销毁前onUnmounted
卸载销毁后
总结:
- Vue3生命周期的函数发生了变化
- 去掉两个:beforeCreate和created,添加了setup
- 方法名称发生变化:方法名称前面多了个on,中间是驼峰式的
- 卸载组件的生命周期变化:onBeforeUnmount 、onUnmounted
- 同一个生命周期可以触发多次
3.组合API-reactive函数
reactive是一个函数,它可以定义一个复杂数据类型,成为响应式数据。
代码演示:
<script>
import { reactive } from 'vue'
export default {
name: 'App',
setup () {
// 数据响应式:数据的变化导致视图自动变化
// let msg = 'hello'
// reactive方法包裹的对象中的数据都是响应式的
const obj = reactive({
msg: 'hello',
info: 'hi'
})
const handleClick = () => {
// msg = 'nihao'
// console.log(msg)
obj.msg = 'nihao'
}
return { obj, handleClick }
}
}
</script>
<style lang="less">
</style
复制代码
总结:
- setup默认返回的普通数据不是响应式的
- 如果希望数据是响应式,有一种做法就是给数据包裹reactive方法即可
4.组合API-toRef函数
定义响应式数据:
- toRef是函数,转换响应式对象中某个属性为单独响应式数据,并且值是关联的。
代码演示:
<template>
<div>
<div>数据的响应式</div>
<hr>
<!-- <div>{{obj.msg}}</div> -->
<div>{{msg}}</div>
<div>{{info}}</div>
<div>
<button @click='handleClick'>点击</button>
</div>
</div>
</template>
<script>
import { reactive, toRef } from 'vue'
export default {
name: 'App',
setup () {
// 需求:模板中必须有添加对象obj前缀,而是直接获取属性
// reactive方法包裹的对象中的数据都是响应式的
const obj = reactive({
msg: 'hello',
info: 'hi'
})
// 把对象中的单个属性取出并且保证数据的响应式
const msg = toRef(obj, 'msg')
const info = toRef(obj, 'info')
const handleClick = () => {
obj.msg = 'nihao'
obj.info = 'coniqiwa'
}
// reactive中的对象属性如果重新赋值会失去响应式能力
return { msg, info, handleClick }
}
}
</script>
<style lang="less">
</style>
复制代码
总结:toRef方法可以把对象中的单个属性取出并且保证响应式能力
5.组合API-toRefs函数
toRefs是函数,转换响应式对象中所有属性(可以是一部分)为单独响应式数据,对象成为普通对象,并且值是关联的 (其实和toRef用法一样,这不过这个可以转换多个对象属性)
6.组合API-ref函数
ref函数,常用于简单数据类型定义为响应式数据
- 在修改值和获取值的时候,需要.value
- 在模板中使用ref申明的响应式数据,可以省略.value
代码演示:
<template>
<div>
<div>数据的响应式</div>
<hr>
<div>{{count}}</div>
<div>
<button @click='handleClick'>点击</button>
</div>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
name: 'App',
setup () {
// ref主要(也可以是对象和数组)用于定义基本类型的数据并保证响应式能力
const count = ref(0)
const obj = ref({ msg: 'hello' })
const handleClick = () => {
// ref定义的数据,在js中操作时需要通过value属性进行
// 但是模板中访问不需要value
count.value += 1
console.log(obj.value.msg)
}
return { count, handleClick }
}
}
</script>
<style lang="less">
</style>
复制代码
总结
- 如果是基本类型数据,可以使用ref进行定义
- ref其实也可以定义对象,但是访问时需要value属性
-
数据响应式
- setup中直接返回的普通数据不是响应式的
- 通过reactive包裹对象可以成为响应式数据
- 为了简化对象的访问(去掉前缀),可以使用toRef进行优化
- 为了获取对象中多个属性,可以使用toRefs进一步简化
- 如果是简单数据类型,其实使用ref定义更加合适