Vue3
为什么要使用 Vue3
1 . 更好的 逻辑复用 与 代码组织 ( composition
组合式 api
)
- Vue3 之前使用的是 optionsAPI(选项式API)
- Vue3 使用的是 compositionAPI(组合式API)
- 优点 : 代码组织更方便了, 逻辑复用更方便了 非常利于维护!!
2 . 更好的 检测类型 ( 类型推导 Typescript
支持 )
-
类型推导 : 就是在没有明确指出类型的变量,
TypeScript
编译器会自动推测变量的类型。 - Vue3 源码用
TypeScript
写的 (TypeScript
可以让代码更加稳定, 更好的检测类型! )
Vue3 新特性
1 . 数据响应式 原理重新实现 ( ES6 的 proxy
替代了 ES5 的 Object.defineProperty
)
- 解决了对象、数组更新后的检测, 大大优化了响应式监听的性能
- 原来检测对象属性的变化, 需要一个个对属性递归监听, proxy 可以直接对整个对象劫持
2 . 虚拟 DOM
- 新算法 (更快 更小)
3 . 提供了 composition api
, 可以更好的逻辑复用
4 . template
模板可以有多个根元素
5 . 源码用 typescript
重写, 有更好的 类型推导 (类型检测更为严格, 更稳定)
小结: vue3 性能更高, 体积更小, 更利于复用, 代码维护更方便
Composition API
options API
vue2 采用的就是 optionsAPI
优点 : 易于学习和使用
, 每个代码有着明确的位置
- 例如 : 数据放 data 中, 方法放 methods 中
缺点 : 相似的逻辑, 不容易复用, 在大项目中尤为明显
注意 : 虽然 optionsAPI
可以通过 mixins
提取相同的逻辑, 但是并不好维护
Composition API
vue3 新增的就是 compositionAPI
-
compositionAPI
是基于 逻辑功能 组织代码的, 一个功能 api 相关放到一起 -
即使项目大了, 功能多了, 也能快速定位功能相关的 api
-
大大的提升了
代码可读性
和可维护性
注意 : vue3 推荐使用 composition API
, 也保留了 options API
- 即就算不用
composition API
, 用 vue2 的写法也 完全兼容
setup
函数
composition
的使用, 需要配置一个 setup
函数
setup
函数特点
-
setup
函数是一个新的组件选项, 作为组件中compositionAPI
的起点 - 从生命周期角度来看,
setup
会在beforeCreate
钩子函数之前执行 - 在
template
模版中需要使用的数据和函数,需要在setup
返回
使用:
<script>
export default {
setup () {
console.log('setup执行了')
console.log(this) // undefined
// 定义数据和函数
const msg = 'hi vue3'
const say = () => {
console.log(msg)
}
return { msg , say}
},
beforeCreate() {
console.log('beforeCreate执行了')
console.log(this)
}
}
</script>
在 template
中使用
<template>
<div>
<h1 @click="say()">{{msg}}</h1>
</div>
</template>
注意 : setup
中不能使用 this
, this
指向 undefined
reactive
函数
setup
中默认普通的数据不是响应式的, 需要用 reactive
函数
作用 : 将复杂类型数据, 转换成响应式数据 ( 返回该对象的响应式代理 )
注意 :
-
setup
需要有返回值, 只有返回的值才能在模板中使用 - 通常是用来定义响应式 对象数据
-
reactive
函数需要按需导入才能使用- 语法 :
import { reactive } from 'vue'
- 语法 :
使用 :
setup ()
中
setup () {
const obj = reactive({
name: 'zs',
age: 18
})
return {
obj
}
template
模板中
<template>
<div>{{ obj.name }}</div>
<div>{{ obj.age }}</div>
</template>
ref
函数
reactive
处理的数据, 必须是 复杂类型, 如果是 简单类型 无法处理成响应式, 所以有 ref
函数
作用 : 对传入的数据(一般简单数据类型),包裹一层对象, 转换成响应式。
ref 函数注意点
-
ref
函数接收一个的值, 返回一个ref
响应式对象- 属性
value
: 可以获取ref响应式对象的值
- 属性
- 在
setup
函数中, 通过value
属性,才可以访问到ref
对象的值 - 在模板中, ref 可以直接使用, 不需要额外的 .value
- ref 函数也支持传入复杂类型,传入复杂类型,也会做响应式处理
- 数组一般使用 ref :
const arr = ref([])
- 数组一般使用 ref :
使用 :
setup ()
中
<script>
import { reactive, ref } from 'vue'
export default {
setup() {
let money = ref(100)
// setup 函数中必须使用 value 属性才能修改值
money.value++
return {
money
}
}
}
</script>
template
模板中
<template>
<div>{{ money }}</div>
<button @click="money++">改值</button>
</template>
注意 : 对象一般使用 reactive
,其他用 ref
toRef
函数
setup
中直接定义的数据 , 不是响应式数据 reactive
函数 , 放的是复杂数据类型
作用 : 使用 toRef函数 , 将 reactive 函数的响应式对象中的指定属性转换为响应式数据
语法 : toRef(参数1, 参数2)
- 参数1 : 目标对象,必须是 响应式对象
- 参数2 : 指定变成响应式对象的属性
用法 :
setup ()
中
<script>
import {reactive,toRef} from 'vue'
/* 目的:setup中直接定义的数据 不是响应式数据 reactive函数 放的是复杂数据类型 */
export default {
setup () {
var obj2={
name:'jack'
}
// 使用reactive函数将obj转变成响应式数据
var obj=reactive({
name:'jack',
age:'18'
})
// var name=toRef(目标对象[要求是响应式对象],指定变成响应式对象的属性)
var name=toRef(obj,'name')
var age=toRef(obj,'age')
const say = () => {
// obj.name='rose'
console.log(name.value)
name.value='lucy'
age.value=20
}
return {say,obj,name,age}
}
}
</script>
template
模板中
<template>
<div>
<input type="button" @click="say()" value="btn"/>
</div>
</template>
toRefs
函数
作用 : 对一个 响应式对象 的所有内部属性, 都做响应式处理, 保证展开或者解构出的数据也是响应式的( 一般配合 reactive
使用)
注意 : 对一个响应数据, 进行 解构 或者 展开, 会丢失他的响应式特性
- 原因 : vue3 底层是对 对象 进行监听劫持
注意 :
- reactive 的响应式功能是赋值给对象的, 如果给对象解构或者展开, 会让数据丢失响应式的能力
- 使用 toRefs 可以保证该对象展开的每个属性都是响应式的
使用 :
setup ()
中
<script>
import { reactive, ref, toRefs } from 'vue'
export default {
setup() {
// const money = ref(100) // 简单类型, ref
// const car = reactive({ // 复杂类型, reactive
// brand: '赛车',
// price: 100
// })
// const name = ref('zs') // 简单类型, ref
// money.value++ // ref需要.value取值
const state = reactive({
money: 100,
car: {
brand: '赛车',
price: 100
},
name: 'zs'
})
return {
...toRefs(state)
}
}
}
</script>
template
模板中
<template>
<div>{{ money }}</div>
<div>{{ car }}</div>
<div>{{ name }}</div>
<button @click="money++">改值</button>
</template>
计算属性 computed
函数
computed 函数调用时, 要接收一个处理函数, 处理函数中, 需要返回计算属性的值
使用 :
computed 是一个函数, 使用前也需要导入
import {computed} from 'vue'
基本用法
- 传入的 实参 是一个 函数
<script>
import { ref, computed } from 'vue'
export default {
setup() {
const age = ref(10)
// 1. 传入一个函数 getter 返回一个值
const nextAge = computed(() => {
return +age.value + 1
})
return {
age,
nextAge
}
}
}
</script>
完整用法
- 传入的 实参 是一个 对象
- 对象中有两个方法
get()
,set()
注意 : 和之前版本一样 - 只要访问计算属性
get()
方法就会被执行 - 计算属性被赋值将会执行
set()
// 2. 传入一个对象, 包括get和set
const nextAge = computed({
get() {
return +age.value + 1
},
set(value) {
age.value = value - 1
}
})
template
模板中
<template>
<input type="text" v-model="age">
<input type="text" v-model="nextAge">
</template>