Vue 3 详细教程

一、Vue 3 简介

Vue.js 是一个渐进式 JavaScript 框架,用于构建用户界面。Vue 3 是 Vue.js 的最新主要版本,于 2020 年 9 月正式发布,带来了许多改进和新特性。

Vue 3 主要新特性

  1. Composition API - 更灵活的逻辑组织和复用方式
  2. 性能提升 - 更快的渲染速度和更小的包体积
  3. 更好的 TypeScript 支持 - 完全使用 TypeScript 重写
  4. 新的响应式系统 - 基于 Proxy 的响应式实现
  5. Fragment、Teleport、Suspense - 新的内置组件

二、环境搭建

1. 使用 Vue CLI 创建项目

npm install -g @vue/cli
vue create my-vue-app
cd my-vue-app
npm run serve

2. 使用 Vite 创建项目(推荐)

npm create vite@latest my-vue-app --template vue
cd my-vue-app
npm install
npm run dev

三、基础语法

1. 模板语法

运行

<template>
  <div>
    <!-- 文本插值 -->
    <h1>{{ message }}</h1>

    <!-- 属性绑定 -->
    <div :id="dynamicId"></div>

    <!-- 事件绑定 -->
    <button @click="handleClick">点击</button>

    <!-- 双向绑定 -->
    <input v-model="inputText">
  </div>
</template>
<script>
export default {
  data() {
    return {
      message: 'Hello Vue 3!',
      dynamicId: 'app-container',
      inputText: ''
    }
  },
  methods: {
    handleClick() {
      console.log('按钮被点击了');
    }
  }
}
</script>

2. 选项式 API vs 组合式 API

选项式 API (Options API)

export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  },
  mounted() {
    console.log('组件已挂载')
  }
}

组合式 API (Composition API)

import { ref, onMounted } from 'vue'
export default {
  setup() {
    const count = ref(0)

    function increment() {
      count.value++
    }

    onMounted(() => {
      console.log('组件已挂载')
    })

    return {
      count,
      increment
    }
  }
}

四、核心概念

1. 响应式基础

ref 和 reactive

import { ref, reactive } from 'vue'
export default {
  setup() {
    // ref 用于基本类型
    const count = ref(0)

    // reactive 用于对象
    const state = reactive({
      name: 'Vue',
      version: 3
    })

    return {
      count,
      state
    }
  }
}

计算属性

import { ref, computed } from 'vue'
export default {
  setup() {
    const firstName = ref('John')
    const lastName = ref('Doe')

    const fullName = computed(() => {
      return `${firstName.value} ${lastName.value}`
    })

    return {
      firstName,
      lastName,
      fullName
    }
  }
}

侦听器

import { ref, watch } from 'vue'
export default {
  setup() {
    const count = ref(0)

    watch(count, (newValue, oldValue) => {
      console.log(`count 从 ${oldValue} 变为 ${newValue}`)
    })

    return {
      count
    }
  }
}

2. 生命周期钩子

选项式 API 组合式 API 描述
beforeCreate - 实例初始化后
created - 实例创建完成后
beforeMount onBeforeMount 挂载开始之前
mounted onMounted 挂载完成后
beforeUpdate onBeforeUpdate 数据更新前
updated onUpdated 数据更新后
beforeUnmount onBeforeUnmount 实例卸载前
unmounted onUnmounted 实例卸载后

3. 组件通信

Props

// 子组件
export default {
  props: {
    title: {
      type: String,
      required: true
    }
  },
  setup(props) {
    console.log(props.title)
  }
}
// 父组件
<ChildComponent title="Hello from parent" />

自定义事件

// 子组件
export default {
  setup(props, { emit }) {
    const handleClick = () => {
      emit('custom-event', 'some data')
    }

    return {
      handleClick
    }
  }
}
// 父组件
<ChildComponent @custom-event="handleEvent" />

provide/inject

// 祖先组件
import { provide } from 'vue'
export default {
  setup() {
    provide('theme', 'dark')
  }
}
// 后代组件
import { inject } from 'vue'
export default {
  setup() {
    const theme = inject('theme', 'light') // 默认值 'light'

    return {
      theme
    }
  }
}

4. 内置组件

Teleport

运行

<teleport to="body">
  <div class="modal">
    这是一个模态框
  </div>
</teleport>

Suspense

运行

<Suspense>
  <template #default>
    <AsyncComponent />
  </template>
  <template #fallback>
    <div>加载中...</div>
  </template>
</Suspense>

五、进阶特性

1. 自定义指令

// 全局指令
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})
// 局部指令
export default {
  directives: {
    highlight: {
      mounted(el) {
        el.style.backgroundColor = 'yellow'
      }
    }
  }
}

2. 插件开发

// myPlugin.js
export default {
  install(app, options) {
    // 添加全局方法或属性
    app.config.globalProperties.$myMethod = () => {
      console.log('这是插件添加的方法')
    }

    // 添加全局指令
    app.directive('my-directive', {
      mounted(el, binding) {
        // 指令逻辑
      }
    })
  }
}
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import myPlugin from './myPlugin'
const app = createApp(App)
app.use(myPlugin, { someOption: true })
app.mount('#app')

3. 使用 TypeScript

// 定义 Props 类型
interface Props {
  msg: string
  count?: number
}
export default defineComponent({
  props: {
    msg: {
      type: String as PropType<string>,
      required: true
    },
    count: {
      type: Number as PropType<number>,
      default: 0
    }
  },
  setup(props: Props) {
    const state = reactive({
      name: 'Vue 3'
    })

    return {
      state
    }
  }
})

4. 状态管理 (Pinia)

Pinia 是 Vue 3 推荐的状态管理库。

npm install pinia
// main.js
import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'
const app = createApp(App)
app.use(createPinia())
app.mount('#app')
// stores/counter.js
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  actions: {
    increment() {
      this.count++
    }
  },
  getters: {
    doubleCount: (state) => state.count * 2
  }
})
// 组件中使用
import { useCounterStore } from '@/stores/counter'
export default {
  setup() {
    const counter = useCounterStore()

    return {
      counter
    }
  }
}

六、路由 (Vue Router)

npm install vue-router@4
// router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: About
  }
]
const router = createRouter({
  history: createWebHistory(),
  routes
})
export default router
// main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
// 组件中使用
import { useRouter, useRoute } from 'vue-router'
export default {
  setup() {
    const router = useRouter()
    const route = useRoute()

    const goToAbout = () => {
      router.push('/about')
    }

    return {
      goToAbout,
      currentPath: computed(() => route.path)
    }
  }
}

七、实战示例

1. Todo List 应用

运行

<template>
  <div>
    <input 
      v-model="newTodo" 
      @keyup.enter="addTodo"
      placeholder="添加新任务"
    >
    <ul>
      <li v-for="(todo, index) in todos" :key="index">
        <input type="checkbox" v-model="todo.completed">
        <span :class="{ completed: todo.completed }">{{ todo.text }}</span>
        <button @click="removeTodo(index)">删除</button>
      </li>
    </ul>
    <p>剩余任务: {{ remaining }} / {{ todos.length }}</p>
  </div>
</template>
<script>
import { ref, computed } from 'vue'
export default {
  setup() {
    const newTodo = ref('')
    const todos = ref([
      { text: '学习 Vue 3', completed: false },
      { text: '完成项目', completed: false }
    ])

    const remaining = computed(() => {
      return todos.value.filter(todo => !todo.completed).length
    })

    function addTodo() {
      if (newTodo.value.trim()) {
        todos.value.push({
          text: newTodo.value,
          completed: false
        })
        newTodo.value = ''
      }
    }

    function removeTodo(index) {
      todos.value.splice(index, 1)
    }

    return {
      newTodo,
      todos,
      remaining,
      addTodo,
      removeTodo
    }
  }
}
</script>
<style>
.completed {
  text-decoration: line-through;
  color: #999;
}
</style>

八、最佳实践

  1. 组件设计
    • 单一职责原则
    • 合理拆分组件
    • 使用有意义的组件名
  2. 代码组织
    • 使用组合式 API 提取可复用逻辑
    • 合理使用自定义 hooks
    • 保持 setup 函数简洁
  3. 性能优化
    • 使用 v-once 和 v-memo 进行静态内容优化
    • 合理使用 computed 和 watch
    • 大型列表使用虚拟滚动
  4. 测试
    • 单元测试 (Vitest/Jest)
    • 组件测试 (Vue Test Utils)
    • E2E 测试 (Cypress)

九、学习资源

  1. Vue 3 官方文档
  2. Vue Mastery
  3. Vue School
  4. Vue.js 中文社区 希望这份详细教程能帮助你掌握 Vue 3!从基础到进阶,Vue 3 提供了强大的功能和灵活的编程模式,适合构建各种规模的应用程序。









results matching ""

    No results matching ""