混入提供了一种将组件中可复用的功能提取出来的方式。理解混入的基础用法是掌握代码复用的关键。
const myMixin = {
data() {
return {
message: 'Hello from mixin'
}
},
methods: {
greet() {
console.log(this.message)
}
}
}
new Vue({
mixins: [myMixin],
created() {
this.greet()
}
})
在组件中使用 mixins 选项引入混入:
<div id="app">
<button @click="greet">问候</button>
<p>{{ message }}</p>
</div>
<script>
const greetMixin = {
data() {
return {
message: 'Hello!'
}
},
methods: {
greet() {
alert(this.message)
}
}
}
new Vue({
el: '#app',
mixins: [greetMixin]
})
</script>
组件可以使用多个混入:
const mixin1 = {
data() {
return {
name: 'mixin1'
}
}
}
const mixin2 = {
data() {
return {
age: 18
}
}
}
new Vue({
mixins: [mixin1, mixin2],
created() {
console.log(this.name)
console.log(this.age)
}
})
混入对象可以包含任何组件选项:
const fullMixin = {
data() {
return {
count: 0
}
},
computed: {
doubleCount() {
return this.count * 2
}
},
methods: {
increment() {
this.count++
}
},
watch: {
count(newVal) {
console.log('count changed:', newVal)
}
},
created() {
console.log('mixin created')
},
mounted() {
console.log('mixin mounted')
}
}
new Vue({
mixins: [fullMixin],
created() {
console.log('component created')
}
})
const mouseTracker = {
data() {
return {
mouseX: 0,
mouseY: 0
}
},
methods: {
updateMousePosition(e) {
this.mouseX = e.clientX
this.mouseY = e.clientY
}
},
mounted() {
window.addEventListener('mousemove', this.updateMousePosition)
},
beforeDestroy() {
window.removeEventListener('mousemove', this.updateMousePosition)
}
}
new Vue({
el: '#app',
mixins: [mouseTracker],
template: `
<div>
鼠标位置: {{ mouseX }}, {{ mouseY }}
</div>
`
})
const windowSize = {
data() {
return {
windowWidth: window.innerWidth,
windowHeight: window.innerHeight
}
},
methods: {
handleResize() {
this.windowWidth = window.innerWidth
this.windowHeight = window.innerHeight
}
},
mounted() {
window.addEventListener('resize', this.handleResize)
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
}
}
const loadingMixin = {
data() {
return {
loading: false
}
},
methods: {
startLoading() {
this.loading = true
},
stopLoading() {
this.loading = false
},
async withLoading(asyncFn) {
this.startLoading()
try {
return await asyncFn()
} finally {
this.stopLoading()
}
}
}
}
new Vue({
mixins: [loadingMixin],
methods: {
async fetchData() {
await this.withLoading(async () => {
const response = await fetch('/api/data')
this.data = await response.json()
})
}
}
})
const formValidationMixin = {
data() {
return {
errors: {}
}
},
methods: {
validate(rules) {
this.errors = {}
let isValid = true
for (const field in rules) {
const value = this.form[field]
const fieldRules = rules[field]
for (const rule of fieldRules) {
const result = rule(value)
if (result !== true) {
this.errors[field] = result
isValid = false
break
}
}
}
return isValid
},
hasError(field) {
return !!this.errors[field]
},
getError(field) {
return this.errors[field]
}
}
}
const paginationMixin = {
data() {
return {
currentPage: 1,
pageSize: 10,
total: 0
}
},
computed: {
totalPages() {
return Math.ceil(this.total / this.pageSize)
},
hasNext() {
return this.currentPage < this.totalPages
},
hasPrev() {
return this.currentPage > 1
}
},
methods: {
goToPage(page) {
this.currentPage = page
this.onPageChange()
},
nextPage() {
if (this.hasNext) {
this.currentPage++
this.onPageChange()
}
},
prevPage() {
if (this.hasPrev) {
this.currentPage--
this.onPageChange()
}
},
onPageChange() {
// 子组件实现
}
}
}
将混入放在单独的文件中:
export const mouseTracker = {
data() {
return {
mouseX: 0,
mouseY: 0
}
},
methods: {
updateMousePosition(e) {
this.mouseX = e.clientX
this.mouseY = e.clientY
}
},
mounted() {
window.addEventListener('mousemove', this.updateMousePosition)
},
beforeDestroy() {
window.removeEventListener('mousemove', this.updateMousePosition)
}
}
在组件中导入:
<script>
import { mouseTracker } from '@/mixins/mouseTracker'
export default {
mixins: [mouseTracker]
}
</script>
适合使用混入的场景:
不适合使用混入的场景:
掌握混入基础后,接下来学习选项合并规则。