Vue 3 Integration Guide
This guide will help you integrate Vant with Vue 3 projects, covering new features, best practices, and optimization strategies.
Vue 3 New Features Support
Composition API Integration
Vant fully supports Vue 3's Composition API, allowing you to use components in a more flexible way:
<template>
<van-button @click="handleClick">{{ buttonText }}</van-button>
<van-field v-model="inputValue" placeholder="Please enter" />
</template>
<script setup>
import { ref, computed } from 'vue'
import { Button, Field } from 'vant'
const inputValue = ref('')
const buttonText = computed(() =>
inputValue.value ? `Input: ${inputValue.value}` : 'Click me'
)
const handleClick = () => {
console.log('Button clicked:', inputValue.value)
}
</script>
Reactive System Deep Integration
Leverage Vue 3's reactive system for better performance:
import { reactive, watch } from 'vue'
import { Toast } from 'vant'
const state = reactive({
loading: false,
data: []
})
// Watch reactive data
watch(() => state.loading, (newVal) => {
if (newVal) {
Toast.loading('Loading...')
} else {
Toast.clear()
}
})
TypeScript Perfect Support
Component Type Definitions
Vant provides complete TypeScript type definitions:
import type { ButtonType, ButtonSize } from 'vant'
interface ButtonConfig {
type: ButtonType
size: ButtonSize
loading: boolean
}
const buttonConfig: ButtonConfig = {
type: 'primary',
size: 'large',
loading: false
}
Event Type Safety
Get full type safety for component events:
<script setup lang="ts">
import { Button } from 'vant'
import type { MouseEvent } from 'vue'
const handleClick = (event: MouseEvent) => {
console.log('Click event:', event)
}
</script>
<template>
<van-button @click="handleClick">Click me</van-button>
</template>
Performance Optimization Strategies
Tree Shaking
Vue 3 + Vant supports better tree shaking:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
build: {
rollupOptions: {
external: ['vue'],
output: {
manualChunks: {
'vant-components': ['vant']
}
}
}
}
})
Component Lazy Loading
Use Vue 3's defineAsyncComponent for lazy loading:
import { defineAsyncComponent } from 'vue'
const LazyComponent = defineAsyncComponent(() =>
import('./components/HeavyComponent.vue')
)
Teleport Integration
Combine Vant components with Vue 3's Teleport:
<template>
<teleport to="body">
<van-overlay :show="showOverlay">
<van-loading />
</van-overlay>
</teleport>
</template>
Theme Customization & Styling
CSS Variables Integration
Use Vue 3's style binding with Vant's CSS variables:
<template>
<div :style="themeVars">
<van-button type="primary">Themed Button</van-button>
</div>
</template>
<script setup>
import { computed } from 'vue'
const props = defineProps(['primaryColor'])
const themeVars = computed(() => ({
'--van-primary-color': props.primaryColor || '#1989fa'
}))
</script>
Dynamic Theme Switching
Implement dynamic theme switching:
import { ref, watchEffect } from 'vue'
const isDark = ref(false)
watchEffect(() => {
document.documentElement.setAttribute(
'data-theme',
isDark.value ? 'dark' : 'light'
)
})
// CSS
// [data-theme="dark"] {
// --van-primary-color: #4fc3f7;
// --van-background-color: #121212;
// }
Best Practices
1. Component Organization
Organize Vant components efficiently:
// composables/useVant.js
import {
Button,
Field,
Form,
Toast,
Dialog
} from 'vant'
export function useVantComponents() {
return {
Button,
Field,
Form,
Toast,
Dialog
}
}
2. Global Configuration
Set up global configurations:
// main.js
import { createApp } from 'vue'
import { ConfigProvider } from 'vant'
import App from './App.vue'
const app = createApp(App)
app.use(ConfigProvider, {
theme: 'light',
themeVars: {
primaryColor: '#1989fa'
}
})
3. Form Handling
Leverage Vue 3's form handling capabilities:
<template>
<van-form @submit="onSubmit">
<van-field
v-model="form.username"
name="username"
label="Username"
placeholder="Username"
:rules="[{ required: true, message: 'Please enter username' }]"
/>
<van-field
v-model="form.password"
type="password"
name="password"
label="Password"
placeholder="Password"
:rules="[{ required: true, message: 'Please enter password' }]"
/>
<div style="margin: 16px;">
<van-button round block type="primary" native-type="submit">
Submit
</van-button>
</div>
</van-form>
</template>
<script setup>
import { reactive } from 'vue'
import { Toast } from 'vant'
const form = reactive({
username: '',
password: ''
})
const onSubmit = (values) => {
console.log('submit', values)
Toast.success('Submit success')
}
</script>
4. State Management Integration
Integrate with Pinia (Vue 3's recommended state management):
// stores/app.js
import { defineStore } from 'pinia'
import { Toast } from 'vant'
export const useAppStore = defineStore('app', {
state: () => ({
loading: false,
theme: 'light'
}),
actions: {
setLoading(loading) {
this.loading = loading
if (loading) {
Toast.loading('Loading...')
} else {
Toast.clear()
}
},
toggleTheme() {
this.theme = this.theme === 'light' ? 'dark' : 'light'
}
}
})
Migration from Vue 2
Key Differences
- Global API Changes: Use
createApp
instead ofnew Vue
- Component Registration: Use app.component() for global registration
- Event Handling: Some event names have changed
- Lifecycle Hooks: Use Composition API lifecycle hooks
Migration Example
Vue 2 style:
// Vue 2
import Vue from 'vue'
import { Button } from 'vant'
Vue.use(Button)
new Vue({
data() {
return {
count: 0
}
},
methods: {
increment() {
this.count++
}
}
})
Vue 3 style:
// Vue 3
import { createApp, ref } from 'vue'
import { Button } from 'vant'
const app = createApp({
setup() {
const count = ref(0)
const increment = () => {
count.value++
}
return {
count,
increment
}
}
})
app.use(Button)
app.mount('#app')
Common Issues and Solutions
1. SSR Support
For server-side rendering with Nuxt 3:
// nuxt.config.ts
export default defineNuxtConfig({
css: ['vant/lib/index.css'],
build: {
transpile: ['vant']
}
})
2. Vite Configuration
Optimize Vite configuration for Vant:
// vite.config.js
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
optimizeDeps: {
include: ['vant']
}
})
3. Testing Setup
Set up testing with Vue Test Utils:
// test setup
import { mount } from '@vue/test-utils'
import { Button } from 'vant'
const wrapper = mount(Button, {
props: {
type: 'primary'
}
})
expect(wrapper.classes()).toContain('van-button--primary')
Conclusion
Vue 3 + Vant provides a powerful combination for building modern mobile applications. By following these best practices and leveraging Vue 3's new features, you can create efficient, maintainable, and performant applications.
For more detailed information, please refer to: