Vue3 使用详解

一、Vue3 简介

Vue3 是 Vue.js 框架的最新主要版本,于 2020 年 9 月正式发布。它带来了许多重大改进和新特性:

  • 性能提升:更快的渲染速度,更小的包体积

  • Composition API:全新的代码组织方式

  • 更好的 TypeScript 支持

  • 新的响应式系统:基于 Proxy 实现

  • Fragment、Teleport、Suspense 等新特性


二、环境搭建

1. 使用 Vite 创建 Vue3 项目

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

2. 使用 Vue CLI 创建项目

npm install -g @vue/cli
vue create my-vue-app
# 选择 Vue 3 预设
cd my-vue-app
npm run serve

三、基础语法

1. 模板语法



2. 响应式基础

Vue3 提供了两种创建响应式数据的方式:

Option API (传统方式)
export default {
  data() {
    return {
      count: 0
    }
  },
  methods: {
    increment() {
      this.count++
    }
  }
}
Composition API (推荐方式)
import { ref } from 'vue'

export default {
  setup() {
    const count = ref(0)
    
    function increment() {
      count.value++
    }
    
    return {
      count,
      increment
    }
  }
}

四、Composition API 详解

1. setup() 函数

setup() 是 Composition API 的入口点,在组件创建之前执行。

import { ref } from 'vue'

export default {
  setup(props, context) {
    // props 是响应式的,不能解构
    console.log(props)
    
    // context 包含 attrs, slots, emit
    console.log(context.attrs)
    
    const count = ref(0)
    
    return {
      count
    }
  }
}

2. 响应式核心

ref

用于创建响应式的基本类型数据

import { ref } from 'vue'

const count = ref(0)
console.log(count.value) // 访问值需要使用 .value
reactive

用于创建响应式的对象

import { reactive } from 'vue'

const state = reactive({
  count: 0,
  user: {
    name: 'John'
  }
})

console.log(state.count) // 直接访问
computed

创建计算属性

import { ref, computed } from 'vue'

const count = ref(0)
const doubleCount = computed(() => count.value * 2)
watch 和 watchEffect

监听数据变化

import { ref, watch, watchEffect } from 'vue'

const count = ref(0)

// 监听特定数据源
watch(count, (newVal, oldVal) => {
  console.log(`count changed from ${oldVal} to ${newVal}`)
})

// 自动追踪依赖
watchEffect(() => {
  console.log(`count is now: ${count.value}`)
})

3. 生命周期钩子

import { onMounted, onUpdated, onUnmounted } from 'vue'

setup() {
  onMounted(() => {
    console.log('组件挂载')
  })
  
  onUpdated(() => {
    console.log('组件更新')
  })
  
  onUnmounted(() => {
    console.log('组件卸载')
  })
}

五、组件开发

1. 组件注册

全局组件
import { createApp } from 'vue'
import App from './App.vue'
import MyComponent from './components/MyComponent.vue'

const app = createApp(App)
app.component('MyComponent', MyComponent)
app.mount('#app')
局部组件
import ComponentA from './ComponentA.vue'

export default {
  components: {
    ComponentA
  }
}

2. Props

// 子组件
export default {
  props: {
    title: {
      type: String,
      required: true,
      default: '默认标题'
    },
    likes: Number
  },
  setup(props) {
    console.log(props.title)
  }
}

3. 自定义事件

// 子组件
setup(props, { emit }) {
  const handleClick = () => {
    emit('custom-event', '事件数据')
  }
  
  return {
    handleClick
  }
}

// 父组件

4. 插槽

默认插槽





  

自定义内容

具名插槽





  
  
  

主要内容

作用域插槽





  

六、高级特性

1. Teleport

将组件渲染到 DOM 树的指定位置



2. Suspense

处理异步组件加载状态



3. 自定义指令

// 全局指令
app.directive('focus', {
  mounted(el) {
    el.focus()
  }
})

// 局部指令
export default {
  directives: {
    highlight: {
      mounted(el, binding) {
        el.style.backgroundColor = binding.value || 'yellow'
      },
      updated(el, binding) {
        el.style.backgroundColor = binding.value || 'yellow'
      }
    }
  }
}

4. 插件开发

// myPlugin.js
export default {
  install(app, options) {
    // 添加全局方法或属性
    app.config.globalProperties.$myMethod = () => {
      console.log('这是插件添加的方法')
    }
    
    // 添加全局指令
    app.directive('my-directive', {
      mounted(el, binding) {
        // 指令逻辑
      }
    })
    
    // 注入全局可用的值
    app.provide('pluginOptions', options)
  }
}

// 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')

七、状态管理 (Pinia)

Pinia 是 Vue3 推荐的状态管理库

1. 安装

npm install pinia

2. 基本使用

// stores/counter.js
import { defineStore } from 'pinia'

export const useCounterStore = defineStore('counter', {
  state: () => ({
    count: 0
  }),
  getters: {
    doubleCount: (state) => state.count * 2
  },
  actions: {
    increment() {
      this.count++
    }
  }
})

// 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')

// 组件中使用
import { useCounterStore } from '@/stores/counter'

export default {
  setup() {
    const counter = useCounterStore()
    
    return {
      counter,
      count: computed(() => counter.count),
      doubleCount: computed(() => counter.doubleCount)
    }
  }
}

八、路由 (Vue Router)

1. 安装

npm install vue-router@4

2. 基本配置

// 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')

3. 在组件中使用




九、进阶技巧

1. 性能优化

  • 使用 v-once 渲染静态内容

  • 使用 v-memo 优化列表渲染

  • 合理使用 computed 和 watch

  • 组件懒加载

  • 使用 keep-alive 缓存组件

2. 自定义渲染器

import { createRenderer } from 'vue'

const { render, createApp } = createRenderer({
  patchProp,
  insert,
  remove,
  createElement,
  // ...其他平台特定API
})

// 然后可以使用这个自定义的 createApp
const app = createApp(App)

3. 与 TypeScript 深度集成

// 定义 Props 类型
interface Props {
  title: string
  count?: number
}

export default defineComponent({
  props: {
    title: {
      type: String as PropType,
      required: true
    },
    count: {
      type: Number as PropType,
      default: 0
    }
  },
  setup(props: Props) {
    // 现在 props 有类型提示了
  }
})

十、实战示例

1. Todo List 应用






十一、常见问题与解决方案

1. 响应式数据不更新

  • 确保使用 ref 或 reactive 创建响应式数据

  • 对于对象,避免直接替换整个对象,应该修改其属性

  • 对于数组,使用可响应的方法如 pushpopsplice 等

2. 生命周期钩子不执行

  • 确保在 setup() 函数中正确注册钩子

  • 检查组件是否被 keep-alive 缓存

3. TypeScript 类型错误

  • 明确声明 props 和 emits 的类型

  • 使用 as PropType 为复杂类型提供类型注解

  • 使用 ! 非空断言操作符时要谨慎


十二、学习资源

  1. Vue3 官方文档

  2. Vue3 迁移指南

  3. Vue Mastery Vue3 课程

  4. Pinia 官方文档

  5. Vue Router 4 文档

你可能感兴趣的:(vue.js,前端,javascript)