Skip to content

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:

<teleport to="body">
  <div class="modal">
    <!-- Renders to body tag -->
  </div>
</teleport>

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

npx nuxi@latest init my-nuxt-app
cd my-nuxt-app
npm install
npm run dev

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>
  • 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.