Vue 3 GuideIntroduction to Vue 3
On September 18, 2020, Vue.js released version 3.0 (https://cn.vuejs.org/guide/introduction.html)
Key Changes in Vue 3
- Performance Improvements
- Bundle size reduced by 41%
- Initial rendering 55% faster, updates 133% faster
- Memory usage reduced by 54%
- Source Code Upgrades
- Uses Proxy instead of defineProperty for reactivity
- Rebuilt virtual DOM implementation and Tree-Shaking
- TypeScript Support
- Better TypeScript integration
- New Features
- Composition API
- New built-in components
- Other enhancements
Creating a Vue Application
Introduction to Vite
Vite official website: https://vitejs.cn
- What is Vite? - A next-generation frontend build tool
- Advantages:
- No bundling during development, fast cold start
- Lightweight and fast HMR
- True on-demand compilation
Creating a Vue Project
How to set up a Vue single-page application locally. The created project will use Vite-based build setup and support Vue single-file components (SFC).
Prerequisites: Node.js 18.3 or higher installed (npm package manager https://nvm.uihtm.com/)
// Create the application
npm create vue@latest
// Initial configuration options
✔ Project name: … <your-project-name>
✔ Add TypeScript? … No / Yes
✔ Add JSX Support? … No / Yes
✔ Add Vue Router for Single Page Application development? … No / Yes
✔ Add Pinia for state management? … No / Yes
✔ Add Vitest for Unit testing? … No / Yes
✔ Add an End-to-End Testing Solution? … No / Cypress / Playwright
✔ Add ESLint for code quality? … No / Yes
✔ Add Prettier for code formatting? … No / Yes
Scaffolding project in ./<your-project-name>...
Done.
// Navigate to project directory
cd <your-project-name>
// Install dependencies
npm install
// Start the project
npm run dev
Entry File (main.js)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
import ArcoVue from '@arco-design/web-vue';
import '@arco-design/web-vue/dist/arco.css';
const app = createApp(App) // Create instance
const pinia = createPinia() // Create Pinia instance
app.use(ArcoVue) // Register Arco components
app.use(pinia) // Mount Pinia
app.use(router) // Mount router
app.mount('#app') // Mount instance, .mount() should be called after all app configuration and resource registration
Common Composition APIs
setup
setup(): The entry point for using Composition API in components.
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return {
count
}
},
}
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
<script setup>: Recommended for Composition API with single-file components.
<script setup>
import { ref } from 'vue'
const count = ref(0)
</script>
<template>
<button @click="count++">{{ count }}</button>
</template>
<style scoped lang="scss">
</style>
ref()
- Can define any data type, requires .value for operations, direct access in templates
- Can reassign entire object via .value
const user = ref({ name: 'Alice' });
user.value = { name: 'Bob' }; // Replace while maintaining reactivity
reactive()
- Defines reactive data of object type, no .value needed for operations
- Limitation: Cannot define primitive data types, cannot reassign entire object
const state = reactive({ name: 'Alice' });
// ❌ Error! Breaks reactivity
state = { name: 'Bob' };
// ✅ Only modify properties
state.name = 'Bob';
Computed()
Similar to Vue 2, different syntax. Expects a getter function, returns a computed ref.
<script setup>
import { ref, computed } from 'vue'
let xing = ref('张')
let ming = ref('三丰')
let xingming = computed(() => {
return xing.value + ming.value
})
</script>
watch()
Similar to Vue 2, different usage scenarios.
<script setup>
import { ref, reactive, watch } from 'vue'
const xing = ref('张')
const ming = ref('三丰')
const person = reactive({
name: '张无忌',
age: 18
})
function changeAge() {
person.age ++
}
watch(xing, (newValue, oldValue) => {
console.log(newValue, oldValue, 'xing被监听了')
}, { immediate: true })
</script>
watchEffect()
Automatically tracks reactive dependencies in the callback.
watchEffect(() => {
const name = xing.value + ming.value
console.log(name, '==watchEffect')
})
Lifecycle Hooks
<script setup>
import { onBeforeMount, onMounted, onBeforeUpdate, onUpdated, onBeforeUnmount, onUnmounted, onActivated, onDeactivated } from 'vue'
onBeforeMount(() => {
console.log('==onBeforeMount==')
})
onMounted(() => {
console.log('==onMounted==')
})
</script>
Composables
"Composables" are functions that encapsulate reusable stateful logic using Vue's Composition API.
// mouse.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 }
}
Components
Registration Methods
- Global Registration
- Local Registration
Props
Parent-child component communication still uses props,单向数据流. .sync modifier is deprecated, use v-model instead.
Events
Trigger custom events using $emit in templates or defineEmits in <script setup>.
Slots
Default slots, named slots, scoped slots work similarly to Vue 2.
Dependency Injection
Use provide() to expose dependencies and inject() to consume them.
v-model
Vue 3.4+ recommends using defineModel() macro for two-way binding.
useAttrs
Access passed-through attributes using useAttrs().
Global API
app.config exposes configuration settings for the application instance.
Built-in Directives and Components
- v-memo: Skips updates for unchanged sub-trees
- <Transition>: Provides animation transitions
- <KeepAlive>: Caches dynamic components
- <Teleport>: Moves template content to another DOM location
Single-File Components
Vue single-file components (SFC) use *.vue extnesion with <template>, <script>, and <style> blocks.
Compiler Macros
- defineProps() and defineEmits()
- defineModel()
- defineExpose()
- defineOptions()
Vue 2 vs Vue 3 Differences
- Root instance creation: new Vue() vs createApp()
- Composition API vs Options API
- Reactivity: Object.defineProperty() vs Proxy
- Lifecycle hooks: beforeCreate/created replaced by setup()
- v-if vs v-for priority
- Template refs: $refs vs ref()
Vue Router
Installation
npm install vue-router@4
Router Instance
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
component: () => import('@/views/layout/index.vue'),
redirect: '/main/home',
children: [
{
path: '/main/home',
name: 'home',
component: () => import('@/views/home/index.vue')
}
]
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
export default router
Navigation Guards
Global, per-route, and component-level guards for controlling navigation.
Pinia
Installation
npm install pinia
Store Definition
Two store types: Option Store and Setup Store.
State Management
Direct state mutation, $patch method, and actions.
Subscriptions
Watch state changes using $subscribe() or watch().
Plugins
Extend Pinia stores with custom functionality.
Common Issues
- beforeRouteEnter guard usage
- Component communication patterns