Vue3入门

文章目录

  • [Vue3 概述](#Vue3 概述)
  • create-vue搭建Vue3项目
  • 项目目录和关键文件
  • [组合式API - setup选项](#组合式API - setup选项)
  • [组合式API - reactive和ref函数](#组合式API - reactive和ref函数)
  • [组合式API - computed](#组合式API - computed)
  • [组合式API - watch](#组合式API - watch)
  • [组合式API - 生命周期钩子](#组合式API - 生命周期钩子)
  • [组合式API - 父子通信](#组合式API - 父子通信)
  • [组合式API - 模版引用](#组合式API - 模版引用)
  • [组合式API - provide和inject](#组合式API - provide和inject)
  • defineOptions
  • defineModel

Vue3 概述

Vue3的优势

Vue2 选项式API 和 Vue3 组合式API

Vue 2(Options API)

js 复制代码
<script>
export default {
  data () {
    return {
      count: 0
    }
  },
  methods: {
    addCount () {
      this.count++
    }
  }
}
</script>

Vue 3(Composition API)

js 复制代码
<script setup>
import { ref } from 'vue'
const count = ref(0)
const addCount = () => count.value++
</script>

代码更加精简,分散式维护转为集中式维护,更易封装复用

create-vue搭建Vue3项目

create-vue是Vue官方新的脚手架工具,底层切换到了 vite(下一代构建工具),为开发提供极速响应

使用create-vue创建项目

  1. 前提环境条件:已安装 16.0 或更高版本的 Node.js
  2. 创建一个Vue应用
bash 复制代码
npm init vue@latest

项目目录和关键文件

文件说明:

  1. vite.config.js - 项目的配置文件 基于vite的配置
  2. package.json - 项目包文件 核心依赖项变成了 Vue3.x 和 vite
  3. main.js - 入口文件 createApp函数创建应用实例
  4. app.vue - 根组件 SFC单文件组件 script - template - style
    变化一:脚本script和模板template顺序调整
    变化二:模板template不再要求唯一根元素
    变化三:脚本script添加setup标识支持组合式API
  5. index.html - 单页入口 提供id为app的挂载点

组合式API - setup选项

setup() 是 Vue 3 引入的组合式 API 的入口函数,用于替代 Options API 中的 data、methods、computed 等逻辑组织方式。它在组件实例创建前执行(早于 beforeCreate),此时 this 还未指向组件实例(值为 undefined)。

普通 <script> 写法(需手动 return)

html 复制代码
<script>
import { ref, onMounted } from 'vue'

export default {
  setup() {
    const count = ref(0)

    const increment = () => {
      count.value++
    }

    onMounted(() => {
      console.log('Component mounted')
    })

    // 必须显式返回才能在模板中使用
    return {
      count,
      increment
    }
  }
}
</script>

<script setup> 语法糖(推荐)

  • 自动暴露内部变量、函数给模板。
  • 编译时转换为标准组合式 API。
  • 不需要 return。
html 复制代码
<script setup>
import { ref, onMounted } from 'vue'

const count = ref(0)

const increment = () => {
  count.value++
}

onMounted(() => {
  console.log('Component mounted')
})
</script>

<template>
  <button @click="increment">{{ count }}</button>
</template>

组合式API - reactive和ref函数

reactive

用于创建响应式的对象(不能用于基本类型)。

基于 Proxy 实现,对对象属性进行深度代理。

html 复制代码
<script setup>
import { reactive } from 'vue'

const state = reactive({
  name: 'Alice',
  age: 25,
  address: {
    city: 'Beijing'
  }
})

// 修改
state.age = 26
state.address.city = 'Shanghai' // 响应式
</script>

不能直接替换整个对象(会丢失响应性):

js 复制代码
// 错误 ❌
state = reactive({ ... }) // 失去响应性

// 正确 ✅
Object.assign(state, { name: 'Bob', age: 30 })

ref

  • 于创建任何类型的响应式数据(包括基本类型、对象、数组)。
  • 内部通过 { value: xxx } 包装,并用 reactive 实现。
  • 在 JS 中访问和修改需加 .value;在模板中自动解包。
html 复制代码
<script setup>
import { ref } from 'vue'

const count = ref(0)
const user = ref({ name: 'Tom' })

// JS 中
count.value++ 
user.value.name = 'Jerry'
</script>
// 模板中(无需 .value)
<template>{{ count }} {{ user.name }}</template>

对比

特性 reactive ref
支持类型 仅对象/数组 所有类型
访问方式 直接属性访问 .value
模板使用 直接 自动解包(无需 .value
替换整个值 不安全 安全(count.value = 100
推荐场景 复杂对象结构 通用,尤其基本类型

✅ 建议:日常开发优先使用 ref,语义统一、不易出错。

组合式API - computed

计算属性基本思想和Vue2的完全一致,组合式API下的计算属性只是修改了写法。

基于响应式依赖计算派生值,具有缓存性(依赖不变则不重新计算)。

只读计算属性

js 复制代码
import { ref, computed } from 'vue'

const price = ref(100)
const tax = ref(0.1)

const totalPrice = computed(() => {
  return price.value * (1 + tax.value)
})

可写计算属性(带 setter)

js 复制代码
const fullName = computed({
  get() {
    return `${firstName.value} ${lastName.value}`
  },
  set(newValue) {
    const [first, last] = newValue.split(' ')
    firstName.value = first
    lastName.value = last
  }
})

组合式API - watch

侦听一个或者多个数据的变化,数据变化时执行回调函数
监听单个响应式数据

js 复制代码
import { ref, watch } from 'vue'

const count = ref(0)

watch(count, (newVal, oldVal) => {
  console.log(`count changed from ${oldVal} to ${newVal}`)
})

监听多个数据

js 复制代码
watch([count, name], ([newCount, newName], [oldCount, oldName]) => {
  console.log('Multiple values changed')
})

监听对象属性(避免 deep)

js 复制代码
const user = reactive({ name: 'Alice', age: 25 })

// 只监听 age 变化,不开启 deep
watch(
  () => user.age,
  (newAge, oldAge) => {
    console.log(`Age changed: ${oldAge} → ${newAge}`)
  }
)

选项配置

js 复制代码
watch(someRef, callback, {
  immediate: true, // 立即执行一次
  deep: true       // 深度监听(适用于对象/数组)
})

注意:第一个参数传 ref 对象本身(如 count),不要写 count.value

组合式API - 生命周期钩子

组合式 API 中需显式导入生命周期函数:

Options API Composition API
beforeCreate ---(直接写在 setup 开头)
created ---
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
js 复制代码
import { onMounted, onUnmounted } from 'vue'

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

onUnmounted(() => {
  console.log('组件即将销毁')
})

同一生命周期可注册多个回调,按顺序执行。

组合式API - 父子通信

父 → 子:Props

html 复制代码
<!-- Parent.vue -->
<Child :title="pageTitle" :user-id="123" />

<!-- Child.vue -->
<script setup>
const props = defineProps({
  title: String,
  userId: {
    type: Number,
    required: true
  }
})
</script>

子 → 父:Emit

html 复制代码
<!-- Child.vue -->
<script setup>
const emit = defineEmits(['update-user', 'close'])

const save = () => {
  emit('update-user', { id: 1, name: 'New Name' })
}
</script>

<!-- Parent.vue -->
<Child @update-user="handleUpdate" @close="onClose" />

组合式API - 模版引用

模版引用通过ref标识获取真实的dom对象或者组件实例对象

js 复制代码
this.$refs.form.validate()

获取 DOM 元素

html 复制代码
<script setup>
import { ref, onMounted } from 'vue'

// 1. 调用ref函数生成一个ref对象
const inputRef = ref(null)

onMounted(() => {
  inputRef.value.focus() // 聚焦输入框
})
</script>

<template>
  <!-- 2. 通过ref标识绑定ref对象到标签 -->
  <input ref="inputRef" />
</template>

获取子组件实例

默认情况下在

html 复制代码
<!-- Child.vue -->
<script setup>
const internalMethod = () => {
  console.log('Called from parent')
}

// 默认不暴露任何内容
defineExpose({
  internalMethod
})
</script>

父组件调用:

js 复制代码
// 1. 调用ref函数生成一个ref对象
const childRef = ref(null)

onMounted(() => {
  childRef.value.internalMethod()
})

<template>
  <!-- 2. 通过ref标识绑定ref对象到标签 -->
  <input ref="childRef" />
</template>

组合式API - provide和inject

顶层组件向任意的底层组件传递数据和方法,实现跨层组件通信
祖先组件提供数据

js 复制代码
// GrandParent.vue
import { provide, ref } from 'vue'

const theme = ref('dark')
const updateTheme = (newTheme) => {
  theme.value = newTheme
}

provide('theme', theme)
provide('updateTheme', updateTheme)

后代组件注入

js 复制代码
// DeepChild.vue
import { inject } from 'vue'

const theme = inject('theme')
const updateTheme = inject('updateTheme')

// 响应式保持:传递的是 ref 对象,不是 .value

defineOptions

解决 <script setup> 中无法设置组件选项的问题。

html 复制代码
<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<script>
// ❌ 不能这样写(两个 script 不兼容)
</script>

正确方式:

html 复制代码
<script setup>
import { ref } from 'vue'

defineOptions({
  name: 'MyCounter',
  inheritAttrs: false
})

const count = ref(0)
</script>

支持的选项:name, inheritAttrs, props, emits(但推荐用专用宏)等。

defineModel

简化 v-model 的实现。
传统方式(繁琐)

js 复制代码
const props = defineProps(['modelValue'])
const emit = defineEmits(['update:modelValue'])

const model = computed({
  get: () => props.modelValue,
  set: (val) => emit('update:modelValue', val)
})

使用 defineModel

html 复制代码
<script setup>
const model = defineModel()

// 直接读写 model
model.value = 'new value'
</script>

<template>
  <input v-model="model" />
</template>

父组件使用:

html 复制代码
<CustomInput v-model="parentValue" />

自动处理 modelValue prop 和 update:modelValue 事件,大幅简化代码。

相关推荐
LawrenceLan1 小时前
17.Flutter 零基础入门(十七):StatelessWidget 与 State 的第一次分离
开发语言·前端·flutter·dart
酷酷的鱼1 小时前
Expo Router vs 原生React Native 完全对比指南
javascript·react native·react.js
桃子叔叔1 小时前
react-wavesurfer录音组件2:前端如何处理后端返回的仅Blob字段
前端·react.js·状态模式
nie_xl1 小时前
VS/TRAE中设置本地maven地址的方法
运维·服务器·前端
烧饼Fighting2 小时前
统信UOS操作系统离线安装ffmpeg
开发语言·javascript·ffmpeg
LV技术派2 小时前
适合很多公司和团队的 AI Coding 落地范式(三)
前端·ai编程·cursor
一只小bit2 小时前
Qt 对话框全方面详解,包含示例与解析
前端·c++·qt·cpp·页面
m0_748254662 小时前
Angular 2 模板语法概述
前端·javascript·angular.js