Vue
Vue.js Overview¶
Vue.js is a progressive JavaScript framework for building user interfaces, created by Evan You in 2014. Vue has become one of the most popular frontend frameworks thanks to its clean syntax, flexible architecture, and excellent performance. Through reactive data binding and a component system, Vue enables developers to efficiently build web applications from simple to complex, and it is also widely adopted in Web3 development.
Official Website: https://vuejs.org/
Core Features¶
1. Reactive System¶
Vue's core mechanism:
- Data Interception: Intercepts data access through Proxy
- Automatic Updates: View updates automatically when data changes
- Dependency Collection: Intelligently tracks data dependencies
- Batch Updates: Asynchronously batches DOM updates
- Fine-Grained Reactivity: Precise updates at the component level
2. Component System¶
Reusable building blocks:
- Single File Components: .vue files encapsulate logic, template, and styles
- Props Passing: Parent-child component communication
- Event Emission: Child-to-parent component communication
- Slots: Flexible content distribution
- Composition API: Vue 3's new composition approach
3. Template Syntax¶
Declarative rendering:
- Interpolation: {{ message }}
- Directives: v-bind, v-if, v-for, v-on
- Modifiers: .prevent, .stop, .once
- Shorthand: : replaces v-bind, @ replaces v-on
- Dynamic Arguments: v-bind:[key]
4. Virtual DOM¶
Performance optimization:
- Virtual Nodes: Lightweight DOM representation
- Diff Algorithm: Efficient difference comparison
- Batch Updates: Reduced DOM operations
- Compile-Time Optimization: Vue 3 compile-time optimizations
- Tree-Shaking: Smaller bundle sizes
Vue 3 New Features¶
Composition API¶
New composition approach:
<script setup>
import { ref, computed, onMounted } from 'vue'
// Reactive data
const count = ref(0)
const doubled = computed(() => count.value * 2)
// Methods
function increment() {
count.value++
}
// Lifecycle
onMounted(() => {
console.log('Component mounted')
})
</script>
<template>
<div>
<p>Count: {{ count }}</p>
<p>Doubled: {{ doubled }}</p>
<button @click="increment">Increment</button>
</div>
</template>
Teleport¶
Teleport component:
Suspense¶
Async components:
<Suspense>
<template #default>
<AsyncComponent />
</template>
<template #fallback>
<div>Loading...</div>
</template>
</Suspense>
Web3 Development¶
Vue + Wagmi¶
Building Web3 applications with Vue:
# Create Vue project
npm create vue@latest my-web3-app
cd my-web3-app
# Install Web3 dependencies
npm install @wagmi/vue @wagmi/core viem
Wallet Connection¶
<script setup>
import { useConnect, useAccount, useDisconnect } from '@wagmi/vue'
import { injected } from '@wagmi/connectors'
const { connect } = useConnect()
const { address, isConnected } = useAccount()
const { disconnect } = useDisconnect()
function handleConnect() {
connect({ connector: injected() })
}
</script>
<template>
<div>
<button v-if="!isConnected" @click="handleConnect">
Connect Wallet
</button>
<div v-else>
<p>Address: {{ address }}</p>
<button @click="disconnect">Disconnect</button>
</div>
</div>
</template>
Reading Contracts¶
<script setup>
import { useReadContract } from '@wagmi/vue'
import { erc20Abi } from 'viem'
const { data: balance } = useReadContract({
address: '0x...',
abi: erc20Abi,
functionName: 'balanceOf',
args: ['0xUserAddress']
})
</script>
<template>
<div>
<p>Balance: {{ balance }}</p>
</div>
</template>
Sending Transactions¶
<script setup>
import { useWriteContract, useWaitForTransactionReceipt } from '@wagmi/vue'
import { erc20Abi, parseUnits } from 'viem'
const { data: hash, writeContract } = useWriteContract()
const { isLoading, isSuccess } = useWaitForTransactionReceipt({
hash
})
function transfer() {
writeContract({
address: '0x...',
abi: erc20Abi,
functionName: 'transfer',
args: ['0xRecipient', parseUnits('1', 18)]
})
}
</script>
<template>
<div>
<button @click="transfer" :disabled="isLoading">
{{ isLoading ? 'Sending...' : 'Send Tokens' }}
</button>
<p v-if="isSuccess">Sent successfully!</p>
</div>
</template>
Ecosystem¶
Core Libraries¶
- Vue Router: Official routing manager
- Pinia: Next-generation state management (replacing Vuex)
- Vue Devtools: Developer tools
- Vite: Ultra-fast build tool
- Vitest: Testing framework
UI Frameworks¶
- Element Plus: Enterprise-grade UI component library
- Vuetify: Material Design components
- Ant Design Vue: Vue version of Ant Design
- Naive UI: Modern component library
- Quasar: Cross-platform framework
Web3 Tools¶
- @wagmi/vue: Wagmi integration for Vue
- vue-dapp: Vue Web3 toolkit
- ethers-vue: Ethers.js Vue wrapper
- web3modal: Wallet connection UI
Nuxt.js¶
Vue's full-stack framework:
Creating a Nuxt Project¶
Server-Side Rendering¶
<!-- pages/index.vue -->
<script setup>
const { data: posts } = await useFetch('/api/posts')
</script>
<template>
<div>
<h1>Post List</h1>
<ul>
<li v-for="post in posts" :key="post.id">
{{ post.title }}
</li>
</ul>
</div>
</template>
API Routes¶
// server/api/posts.ts
export default defineEventHandler(async (event) => {
const posts = await fetchPosts()
return posts
})
Best Practices¶
1. Component Design¶
- Single responsibility principle
- Props type validation
- Appropriate use of slots
- Avoid deeply nested structures
- Reuse common logic
2. Performance Optimization¶
<script setup>
import { computed, watch } from 'vue'
// Use computed to cache calculation results
const filteredList = computed(() => {
return list.value.filter(item => item.active)
})
// Use watchEffect to automatically track dependencies
watchEffect(() => {
console.log(count.value)
})
</script>
<template>
<!-- Use v-once to render only once -->
<div v-once>{{ staticContent }}</div>
<!-- Use key to optimize list rendering -->
<div v-for="item in items" :key="item.id">
{{ item.name }}
</div>
</template>
3. State Management¶
Using Pinia:
// stores/counter.ts
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0
}),
getters: {
doubled: (state) => state.count * 2
},
actions: {
increment() {
this.count++
}
}
})
4. TypeScript Support¶
<script setup lang="ts">
interface Props {
title: string
count?: number
}
const props = withDefaults(defineProps<Props>(), {
count: 0
})
const emit = defineEmits<{
update: [value: number]
delete: [id: string]
}>()
</script>
Related Concepts and Technologies¶
- React: UI library developed by Facebook
- Svelte: Compile-time framework
- Angular: Full-stack framework developed by Google
- Vite: Next-generation frontend build tool
- Pinia: Vue state management library
Summary¶
Vue.js has become a popular choice in frontend development thanks to its progressive design philosophy, elegant API, and powerful ecosystem. Vue 3's Composition API and performance optimizations make it even more powerful and flexible. In Web3 development, Vue also delivers an excellent development experience through tools like @wagmi/vue. Whether building traditional web applications or decentralized applications, Vue provides efficient, elegant solutions.