基本用法
假设我们有一个通用的功能,如日志记录,我们可以用 Mixin 来实现它。在 Vue 3 中,这个功能可以用组合式 API 来实现。
- 创建一个组合函数,首先,我们创建一个组合函数来封装共享的逻辑:
// useLogger.js
import { onMounted, onUnmounted } from 'vue'
export function useLogger() {
onMounted(() => {
console.log('Component mounted')
})
onUnmounted(() => {
console.log('Component unmounted')
})
}
- 在组件中使用组合函数接下来,我们在组件中使用这个组合函数:
<template>
<div>
<p>Check the console for log messages.</p>
</div>
</template>
<script setup>
import { useLogger } from './useLogger.js'
useLogger()
</script>
使用场景
- 代码复用将通用的逻辑提取到组合函数中,实现代码复用。
// useFetchData.js
import { ref, onMounted } from 'vue'
export function useFetchData(url) {
const data = ref(null)
const error = ref(null)
onMounted(async () => {
try {
const response = await fetch(url)
data.value = await response.json()
} catch (err) {
error.value = err
}
})
return { data, error }
}
- 响应式状态管理将共享的状态管理逻辑提取到组合函数中。
// useCounter.js
import { ref } from 'vue'
export function useCounter() {
const count = ref(0)
const increment = () => {
count.value++
}
return { count, increment }
}
- 生命周期钩子复用将通用的生命周期钩子逻辑提取到组合函数中。
// useLifecycleLogger.js
import { onMounted, onUnmounted } from 'vue'
export function useLifecycleLogger() {
onMounted(() => {
console.log('Component mounted')
})
onUnmounted(() => {
console.log('Component unmounted')
})
}
- 复杂逻辑拆分将复杂的逻辑拆分成多个组合函数,增强代码的可读性和可维护性。
// useComplexLogic.js
import { ref, watch } from 'vue'
export function useComplexLogic() {
const state = ref(0)
const result = ref(null)
const computeResult = () => {
// 一些复杂的计算逻辑
result.value = state.value * 2
}
watch(state, computeResult)
return { state, result }
}
在组件中使用组合函数(示例)
<template>
<div>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<p>Result: {{ result }}</p>
</div>
</template>
<script setup>
import { useCounter } from './useCounter.js'
import { useComplexLogic } from './useComplexLogic.js'
const { count, increment } = useCounter()
const { state, result } = useComplexLogic()
state.value = count.value
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vue 3 Mixin Example</title>
<script type="module" src="https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js"></script>
</head>
<body>
<div id="app"></div>
<script type="module">
import { createApp, defineComponent, h } from 'https://unpkg.com/vue@3.2.47/dist/vue.esm-browser.js';
// 定义一个 Mixin
const countMixin = {
data () {
return {
count: 0
};
},
methods: {
increment () {
this.count++;
},
decrement () {
this.count--;
}
}
};
// 定义第一个组件
const ComponentOne = defineComponent({
mixins: [countMixin],
template: `
<div>
<h1>Component One</h1>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
`
});
// 定义第二个组件
const ComponentTwo = defineComponent({
mixins: [countMixin],
template: `
<div>
<h1>Component Two</h1>
<p>Count: {{ count }}</p>
<button @click="increment">Increment</button>
<button @click="decrement">Decrement</button>
</div>
`
});
// 定义第二个组件
const ComponenTthr = defineComponent({
mixins: [countMixin],
render () {
return h('div', [
h('h1', 'Component Three'),
h('p', `Count: ${this.count}`),
h('button', { onClick: this.increment }, 'Increment'),
h('button', { onClick: this.decrement }, 'Decrement')
]);
}
});
// 创建主应用
const App = defineComponent({
components: {
ComponentOne,
ComponentTwo
},
template: `
<div>
<ComponentOne />
<ComponentTwo />
</div>
`,
render () {
return h('div', [
h(ComponenTthr)
]);
}
});
createApp(App).mount('#app');
</script>
</body>
</html>