243 lines
3.8 KiB
Markdown
243 lines
3.8 KiB
Markdown
# 组合式API
|
|
|
|
## setup函数
|
|
|
|
### 基本用法
|
|
|
|
```vue
|
|
<script setup>
|
|
import { ref, reactive, computed, watch, onMounted } from 'vue'
|
|
|
|
// 响应式数据
|
|
const count = ref(0)
|
|
const state = reactive({
|
|
name: 'Vue',
|
|
version: 3
|
|
})
|
|
|
|
// 计算属性
|
|
const doubleCount = computed(() => count.value * 2)
|
|
|
|
// 方法
|
|
function increment() {
|
|
count.value++
|
|
}
|
|
|
|
// 生命周期
|
|
onMounted(() => {
|
|
console.log('组件已挂载')
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<p>Count: {{ count }}</p>
|
|
<p>Double: {{ doubleCount }}</p>
|
|
<button @click="increment">+1</button>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
## ref与reactive
|
|
|
|
### ref
|
|
|
|
用于基本类型和需要替换整个对象的场景。
|
|
|
|
```vue
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
|
|
const count = ref(0)
|
|
const user = ref({ name: '张三' })
|
|
|
|
// 访问需要 .value
|
|
console.log(count.value)
|
|
console.log(user.value.name)
|
|
|
|
// 重新赋值
|
|
user.value = { name: '李四' }
|
|
</script>
|
|
```
|
|
|
|
### reactive
|
|
|
|
用于对象类型,返回原始对象的代理。
|
|
|
|
```vue
|
|
<script setup>
|
|
import { reactive } from 'vue'
|
|
|
|
const state = reactive({
|
|
count: 0,
|
|
user: {
|
|
name: '张三',
|
|
age: 25
|
|
}
|
|
})
|
|
|
|
// 直接访问,不需要 .value
|
|
console.log(state.count)
|
|
console.log(state.user.name)
|
|
|
|
// 修改属性
|
|
state.count++
|
|
state.user.age = 26
|
|
</script>
|
|
```
|
|
|
|
## 组合式函数
|
|
|
|
### 创建组合式函数
|
|
|
|
```javascript
|
|
// useCounter.js
|
|
import { ref, computed } from 'vue'
|
|
|
|
export function useCounter(initialValue = 0) {
|
|
const count = ref(initialValue)
|
|
|
|
const doubleCount = computed(() => count.value * 2)
|
|
|
|
function increment() {
|
|
count.value++
|
|
}
|
|
|
|
function decrement() {
|
|
count.value--
|
|
}
|
|
|
|
function reset() {
|
|
count.value = initialValue
|
|
}
|
|
|
|
return {
|
|
count,
|
|
doubleCount,
|
|
increment,
|
|
decrement,
|
|
reset
|
|
}
|
|
}
|
|
```
|
|
|
|
### 使用组合式函数
|
|
|
|
```vue
|
|
<script setup>
|
|
import { useCounter } from './useCounter'
|
|
|
|
const { count, doubleCount, increment, decrement, reset } = useCounter(10)
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<p>Count: {{ count }}</p>
|
|
<p>Double: {{ doubleCount }}</p>
|
|
<button @click="increment">+1</button>
|
|
<button @click="decrement">-1</button>
|
|
<button @click="reset">Reset</button>
|
|
</div>
|
|
</template>
|
|
```
|
|
|
|
### 鼠标位置追踪
|
|
|
|
```javascript
|
|
// useMouse.js
|
|
import { ref, onMounted, onUnmounted } from 'vue'
|
|
|
|
export function useMouse() {
|
|
const x = ref(0)
|
|
const y = ref(0)
|
|
|
|
function update(event) {
|
|
x.value = event.pageX
|
|
y.value = event.pageY
|
|
}
|
|
|
|
onMounted(() => {
|
|
window.addEventListener('mousemove', update)
|
|
})
|
|
|
|
onUnmounted(() => {
|
|
window.removeEventListener('mousemove', update)
|
|
})
|
|
|
|
return { x, y }
|
|
}
|
|
```
|
|
|
|
```vue
|
|
<script setup>
|
|
import { useMouse } from './useMouse'
|
|
|
|
const { x, y } = useMouse()
|
|
</script>
|
|
|
|
<template>
|
|
<p>鼠标位置: {{ x }}, {{ y }}</p>
|
|
</template>
|
|
```
|
|
|
|
## provide/inject
|
|
|
|
### 提供数据
|
|
|
|
```vue
|
|
<!-- 祖先组件 -->
|
|
<script setup>
|
|
import { provide, ref } from 'vue'
|
|
|
|
const theme = ref('dark')
|
|
const user = ref({ name: '张三' })
|
|
|
|
provide('theme', theme)
|
|
provide('user', user)
|
|
provide('updateTheme', (newTheme) => {
|
|
theme.value = newTheme
|
|
})
|
|
</script>
|
|
```
|
|
|
|
### 注入数据
|
|
|
|
```vue
|
|
<!-- 后代组件 -->
|
|
<script setup>
|
|
import { inject } from 'vue'
|
|
|
|
const theme = inject('theme', 'light') // 默认值
|
|
const user = inject('user')
|
|
const updateTheme = inject('updateTheme')
|
|
|
|
function toggleTheme() {
|
|
updateTheme(theme.value === 'dark' ? 'light' : 'dark')
|
|
}
|
|
</script>
|
|
```
|
|
|
|
## toRef与toRefs
|
|
|
|
```vue
|
|
<script setup>
|
|
import { reactive, toRef, toRefs } from 'vue'
|
|
|
|
const state = reactive({
|
|
name: '张三',
|
|
age: 25,
|
|
city: '北京'
|
|
})
|
|
|
|
// toRef - 单个属性
|
|
const nameRef = toRef(state, 'name')
|
|
|
|
// toRefs - 所有属性
|
|
const { name, age, city } = toRefs(state)
|
|
|
|
// 解构后的ref保持响应性
|
|
name.value = '李四'
|
|
console.log(state.name) // 李四
|
|
</script>
|
|
```
|