目录
本文主要介绍Vue 3中的数据选项,包括data、computed、method、watch、props、provide/inject等。
什么是数据选项?
在Vue3中,数据选项指的是用于定义Vue实例中数据的属性。数据选项可以包括响应式数据、计算属性、方法和侦听等,用于定义Vue实例的数据模型。
下面介绍几种常见的数据选项:
1. reactive data(响应式数据)
在Vue3中,响应式数据使用ref
和reactive
包装。ref
用于包装简单数据类型,比如数字、字符串、布尔值等,而reactive
用于包装对象和数组等复杂数据类型。这样包装之后,这些数据就可以被Vue3追踪,并在数据发生变化时自动更新相关的视图。
在我之前写的文章《Vue 3 的响应式数据》有详细介绍。
2. computed(计算属性)
计算属性是指根据已有属性计算出新的属性,通常用于简化模板中的表达式。在Vue3中,计算属性可以使用computed
函数来定义,与Vue2中类似。
下面举一个例子,在<script setup>
中定义计算属性,可以直接在模板中使用,而不需要像Vue 2.x版本一样必须将计算属性添加到computed
选项中。下面是一个在<script setup>
中定义计算属性的例子:
<template>
<div>
<p>{{ fullName }}</p>
</div>
</template>
<script setup>
const firstName = 'John'
const lastName = 'Doe'
const fullName = () => {
return `${firstName} ${lastName}`
}
</script>
在这个例子中,我们在<script setup>
块中定义了firstName
、lastName
和fullName
。fullName
是一个箭头函数,它返回拼接后的完整名字。在模板中,我们可以直接访问计算属性fullName
并渲染结果,就像在Vue 2.x版本中那样。
注意,在使用<script setup>
时,不需要使用computed
选项来定义计算属性。
3. method(方法)
方法是指在Vue实例中定义的函数,可以在模板中通过指令调用。在Vue3中,方法和计算属性一样,可以使用普通函数来定义。不过也可以使用methods
对象来定义多个方法,与Vue2中类似。
在 <script setup>
中定义方法很简单,只需要直接在代码块中定义即可。下面是一个使用 <script setup>
定义方法的例子:
```html
<template>
<div>
<button @click="incrementCounter">点击增加</button>
<p>计数器值:{{ counter }}</p>
</div>
</template>
<script setup>
let counter = 0
const incrementCounter = () => {
counter++
}
</script>
```
在这个例子中,我们在 <script setup>
块中定义了 counter
数据选项和 incrementCounter
方法。当按钮被点击时,incrementCounter
方法将计数器值加 1,而模板中的计数器值则会自动更新。
需要注意的是,在使用 <script setup>
时,需要使用 let
或 const
关键字来声明数据选项。此外,需要将方法定义为一个函数,而不是使用对象语法。
4. watch(侦听)
在Vue3中,侦听(watch)是处理数据变化的一种方式,类似于Vue2中的watch
选项。但是,在Vue3中,侦听的用法和实现方式都有所变化。
Vue3中通过watchEffect
和watch
两个API实现侦听。其中,watchEffect
用于响应式监听数据变化,自动执行其内部的处理函数;而watch
则更加灵活,可以监听多个数据源并执行回调函数,支持深度监听、立即执行等高级选项。
下面分别介绍watchEffect
和watch
的使用方法:
(1) watchEffect
的使用方法:
import { watchEffect, reactive } from 'vue'
const state = reactive({ count: 0 })
watchEffect(() => {
console.log(state.count) // 自动响应式监听数据变化
})
上面代码中,watchEffect
会自动侦听state.count
的变化,并在变化时执行其内部的处理函数(即控制台输出state.count
的值)。
(2) watch
的使用方法:
import { watch, reactive } from 'vue'
const state = reactive({ count: 0, name: 'Vue3' })
watch([
() => state.count, // 监听state.count的变化
() => state.name // 监听state.name的变化
], ([count, name], [prevCount, prevName]) => {
console.log(`count: ${count}, name: ${name}`) // 执行回调函数
}, {
deep: true, // 深度监听
immediate: true // 立即执行
})
上面代码中,watch
可以同时监听多个数据源(即state.count
和state.name
),并在变化时执行其回调函数。回调函数的第一个参数为新值,第二个参数为旧值。在选项对象中,可以配置deep
和immediate
等高级选项。
Vue3中的侦听相比于Vue2更加灵活和高效,可以更好地处理数据变化和业务逻辑。
5. props
用于父组件向子组件传递数据的属性列表,通过props选项将其声明为子组件的属性,子组件通过props来接收这些属性。
下面是一个使用<script setup>
编写的父子组件,其中父组件向子组件传递一个message
属性:
<!-- Parent.vue (父组件)-->
<template>
<Child :message="parentMessage" />
</template>
<script setup>
import Child from './Child.vue'
const parentMessage = 'Hello from parent'
</script>
<script>
export default {
components: { Child },
data() {
return {
parentMessage
}
}
}
</script>
<!-- Child.vue (子组件)-->
<template>
<div>{{ message }}</div>
</template>
<script setup>
import { defineProps } from 'vue'
const props = defineProps({
message: {
type: String,
default: 'Hello from child'
}
})
</script>
在上面的代码中,父组件Parent.vue
通过<Child :message="parentMessage" />
向子组件Child.vue
传递了一个message
属性。子组件通过defineProps
函数来定义了一个props
对象,其中包含了一个名为message
的属性,它的类型为String
,默认值为Hello from child
。在模板中,子组件通过props.message
来获取message
属性的值。
6. provide/inject
用于祖先组件向后代组件传递数据的高级选项。通过provide选项将一个数据对象提供给子组件,子组件通过inject选项来接收这个数据对象。
假设我们有一个父组件和一个子组件,我们希望在父组件中提供一些数据给子组件使用。我们可以使用 provide
在父组件中提供数据,然后使用 inject
在子组件中注入这些数据。
<template>
<div>
<p>父组件:</p>
<p>name: {{name}}</p>
<p>age: {{age}}</p>
<hr>
<Child />
</div>
</template>
<script setup>
import Child from './Child.vue'
const name = '张三'
const age = 18
provide('personInfo', { name, age })
</script>
在父组件中,我们使用了 provide
提供了一个名为 personInfo
的数据,它是一个对象,包含了 name
和 age
两个属性。
<template>
<div>
<p>子组件:</p>
<p>name: {{name}}</p>
<p>age: {{age}}</p>
</div>
</template>
<script setup>
import { inject } from 'vue'
const { name, age } = inject('personInfo', {
name: '未知',
age: 0
})
</script>
在子组件中,我们使用了 inject
注入了在父组件中提供的 personInfo
数据,并将它们解构为 name
和 age
两个变量使用。在 inject
中,我们还可以传入一个默认值对象,在没有注入到数据时使用。这里我们传入了一个默认的名为 未知
,年龄为 0
的数据。
这样,在子组件中,我们就可以通过 name
和 age
两个变量访问在父组件中提供的数据了。