围绕最新发布的 vue-compisition-api,同时也是 vue 3.0 最重要的一些新特性,例如 setup() 函数、reactive()、ref() 等这些 Vue Hooks
创建一个 vue3.0-beta项目
// 安装 composition-api 体验 vue3 新特性
npm install @vue/composition-api --save
setup()
函数是 vue3 中,专门为组件提供的新属性。它为我们使用 vue3 的 Composition API
新特性提供了统一的入口
setup 函数会在 beforeCreate 之后、created 之前执行
第一个形参 props 用来接收 props
数据
// 父组件
<div p1="aaa"></div>
// 子组件
setup(props) {
console.log(props.p1) // aaa
},
props: {
p1: String
}
第二个形参 context 用来定义上下文
这个上下文对象中包含了一些有用的属性,这些属性在 vue 2.x 中需要通过 this 才能访问到,在 vue 3.x 中,它们的访问方式如下:
const MyComponent = {
setup(props, context) {
context.attrs
context.slots
context.parent
context.root
context.emit
context.refs
}
}
注意:在 setup() 函数中无法访问到 this,是个 undefined
reactive()
函数接收一个普通对象,返回一个响应式的数据对象
// 3. 在 template 中访问响应式数据
<p>当前的 count 值为:{
{
count}}</p>
<button @click="count+=1">+1</button>
// 1. 按需导入 reactive 函数
import {
reactive } from 'vue'
// 2. 在 setup() 函数中调用 reactive() 函数,创建响应式数据对象
setup() {
// 创建响应式数据对象,类似于 vue 2.x 中 data() 返回的响应式对象
const state = reactive({
count: 0})
// setup 函数中将响应式数据对象 return 出去,供 template 使用
return state
}
渲染结果:
当前count的值为: 0
+1
ref()
函数用来根据给定的值创建一个响应式的数据对象,ref()
函数调用的返回值是一个对象,这个对象上只包含一个 value
属性
import {
ref } from 'vue'
setup () {
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
}
在 template 中访问响应式数据
<p>{
{
count}}</p>
import {
ref } from 'vue'
setup () {
const count = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
return {
count}
}
// 1
注意:只在
setup
函数内部访问ref
函数需要加.value
在 reactive 对象中访问 ref 创建的响应式数据
import {
ref, reactive } from 'vue'
setup () {
const count = ref(0)
count.value++
const state = reactive({
count})
console.log(state.count) // 1
return {
state }
}
新的 ref 会覆盖旧的 ref,示例代码如下:
// 创建 ref 并挂载到 reactive 中
const c1 = ref(0)
const state = reactive({
c1
})
// 再次创建 ref,命名为 c2
const c2 = ref(9)
// 将 旧 ref c1 替换为 新 ref c2
state.c1 = c2
state.c1++
console.log(state.c1) // 输出 10
console.log(c2.value) // 输出 10
console.log(c1.value) // 输出 0
isRef()
用来判断某个值是否为 ref() 创建出来的对象
应用场景:当需要展开某个可能为 ref() 创建出来的值的时候
import {
ref, isRef } from 'vue'
setup() {
const foo = ref(0)
const isFoo = isRef(foo) ? foo.value : foo
console.log(isFoo) // 0
}
toRefs()
函数可以将 reactive()
创建出来的响应式对象,转换为普通的对象,只不过,这个对象上的每个属性节点,都是 ref()
类型的响应式数据,最常见的应用场景如下
<p>{
{
count }}</p>
<button @click="increment">+1</button>
import {
toRefs, reactive } from 'vue'
setup() {
const state = reactive({
count: 0,
naem: 'zs'
})
const increment = () => {
state.count++
}
return {
// 将 state 上的每个属性,都转化为 ref 形式的响应式数据
...toRefs(state),
increment
}
}
import {
computed, ref } from 'vue'
setup () {
// 创建一个 ref 响应式数据
const count = ref(1)
// 根据 count 的值,创建一个响应式的计算属性 plusOne
// 它会根据依赖的 ref 自动计算并返回一个新的 ref
const plusOne = computed(() => count.value + 1)
console.log(plusOne.value) // 输出 2
return {
count, plusOne}
}
const count2 = ref(1)
// 创建一个 computed 计算属性
const plusTwo = computed({
// 取值函数
get: () => count2.value + 1,
// 赋值函数
set: val => {
count2.value = val - 1
}
})
// 为计算属性赋值的操作,会触发 set 函数
plusTwo.value = 9
// 触发 set 函数后,count 的值会被更新
console.log(count2.value) // 输出 8
import {
watch, ref } from 'vue'
setup () {
const count = ref(0)
// 定义 watch,只要 count 值变化,就会触发 watch 回调
// watch 会在创建时会自动调用一次
watch(() => console.log(count.value))
// 输出 0
setTimeout(() => {
count.value++
// 输出 1
}, 1000)
}
// 定义数据源
const state = reactive({
count: 0 })
// 监视 state.count 这个数据节点的变化
watch(
() => state.count,
(count, prevCount) => {
/* ... */
}
)
2.2 监视 ref 类型的数据源:
// 定义数据源
const count = ref(0)
// 指定要监视的数据源
watch(count, (count, prevCount) => {
/* ... */
})
const state = reactive({
count: 0, name: 'zs' })
watch(
[() => state.count, () => state.name],
([count, name], [prevCount, prevName]) => {
console.log(count) // 新的 count 值
console.log(name) // 新的 name 值
console.log('------------')
console.log(prevCount) // 旧的 count 值
console.log(prevName) // 新的 name 值
},
{
lazy: true // 在 watch 被创建的时候,不执行回调函数中的代码
}
)
setTimeout(() => {
state.count++
state.name = 'ls'
}, 1000)
// 创建监视,并得到 停止函数
const stop = watch(() => {
/* ... */
})
// 调用停止函数,清除对应的监视
stop()
新版的生命周期函数,可以按需导入到组件中,且只能在 setup() 函数中使用,代码示例如下:
import {
onMounted, onUpdated, onUnmounted } from 'vue'
const MyComponent = {
setup() {
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
}
}
下面的列表,是 vue 2.x 的生命周期函数与新版 Composition API 之间的映射关系:
beforeCreate -> use setup()
created -> use setup()
beforeMount -> onBeforeMount
mounted -> onMounted
beforeUpdate -> onBeforeUpdate
updated -> onUpdated
beforeDestroy -> onBeforeUnmount
destroyed -> onUnmounted
errorCaptured -> onErrorCaptured