Vue3进阶入门指南

Vue3 进阶:从选项式 API 到组件通信

学完 Vue3 的基础语法后,真正影响开发效率的往往不是某一个指令,而是能不能把组件、状态、表单和生命周期串起来使用。本文围绕 Vue3 中最常见的进阶知识点展开:选项式 API、单文件组件、应用挂载、表单处理、组件复用、props 传值、子组件事件通信以及生命周期钩子。

如果你已经能写出简单页面,但还不确定 Vue 组件内部的数据如何组织、父子组件如何协作、生命周期代码应该放在哪里,这篇文章可以作为一份清晰的梳理。

1. 选项式 API:用对象组织组件逻辑

Vue3 同时支持组合式 API 和选项式 API。对于刚开始进阶的同学来说,选项式 API 更直观:组件的状态、方法、计算属性和生命周期钩子都被放在一个对象中。

vue 复制代码
<script>
export default {
  // data() 返回的属性会成为响应式状态
  // 并且可以通过 this 访问
  data() {
    return {
      count: 0,
      author: {
        books: ['Vue Guide']
      }
    }
  },

  // methods 用来声明事件处理函数或普通方法
  methods: {
    increment() {
      this.count++
    }
  },

  // computed 用来声明依赖响应式数据的计算结果
  computed: {
    publishedBooksMessage() {
      return this.author.books.length > 0 ? 'Yes' : 'No'
    }
  },

  // mounted 会在组件挂载完成后执行
  mounted() {
    console.log(`The initial count is ${this.count}.`)
  }
}
</script>

<template>
  <button @click="increment">Count is: {{ count }}</button>
  <p>Has published books: {{ publishedBooksMessage }}</p>
</template>

这段代码包含了选项式 API 的几个核心部分:

  • data:声明组件内部的响应式数据。
  • methods:声明组件方法,常用于事件处理。
  • computed:声明计算属性,适合处理由状态推导出的结果。
  • mounted:生命周期钩子,适合在组件完成初始渲染后执行逻辑。

当组件逻辑还不复杂时,选项式 API 的结构非常清楚;随着业务增长,也可以逐步过渡到组合式 API。

2. 单文件组件:把结构、逻辑和样式放在一起

Vue 项目中最常见的组件形式是 .vue 单文件组件。它通常由三个区域组成:scripttemplatestyle

vue 复制代码
<script>
export default {
  data() {
    return {
      count: 0
    }
  }
}
</script>

<template>
  <button @click="count++">Count is: {{ count }}</button>
</template>

<style scoped>
button {
  font-weight: bold;
}
</style>

其中:

  • <script> 负责组件逻辑。
  • <template> 负责页面结构。
  • <style scoped> 负责当前组件样式,scoped 可以让样式尽量只作用于当前组件。

单文件组件的好处是边界清晰,适合复用和维护。一个按钮、一个列表、一张卡片,甚至一个完整页面,都可以被拆成组件。

3. 根组件与应用挂载

Vue 应用需要通过 createApp 创建应用实例,再挂载到页面中的某个 DOM 节点上。

vue 复制代码
import { createApp } from 'vue'

const app = createApp({
  data() {
    return {
      count: 0
    }
  }
})

app.mount('#app')

这里的 #app 对应 HTML 中的根节点:

html 复制代码
<div id="app"></div>

可以把根组件理解为整个 Vue 应用的入口。实际项目中,我们通常会把根组件写成 App.vue,再在 main.jsmain.ts 中完成挂载。

4. 表单处理:用 v-model 简化双向绑定

表单是前端项目中非常高频的场景。Vue 提供了 v-model,可以让输入框的值和组件状态保持同步。

文本输入

vue 复制代码
<p>Message is: {{ message }}</p>
<input v-model="message" placeholder="edit me" />

当用户输入内容时,message 会自动更新;当 message 被代码修改时,输入框也会同步变化。

多行文本

vue 复制代码
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>

多行文本常用于评论、备注、说明等场景。展示时可以配合 white-space: pre-line; 保留换行效果。

复选框

vue 复制代码
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>

单个复选框通常绑定布尔值,适合表示"是否启用""是否同意"等状态。

单选按钮

vue 复制代码
<div>Picked: {{ picked }}</div>

<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>

<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>

多个单选按钮绑定同一个变量,变量值会等于当前被选中的 value

选择器

单选选择器:

vue 复制代码
<div>Selected: {{ selected }}</div>

<select v-model="selected">
  <option disabled value="">Please select one</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

多选选择器:

vue 复制代码
<div>Selected: {{ selected }}</div>

<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>

如果选项来自接口或配置,可以使用 v-for 动态渲染:

vue 复制代码
<div>Selected: {{ selected }}</div>

<select v-model="selected">
  <option
    v-for="option in options"
    :key="option.value"
    :value="option.value"
  >
    {{ option.text }}
  </option>
</select>

这里建议给 v-for 添加 key,这样 Vue 可以更稳定地追踪列表节点。

5. 组件基础:定义组件与使用组件

组件可以理解为可复用的 UI 单元。一个 .vue 文件通常就是一个组件。

例如,我们定义一个 ButtonCounter.vue

vue 复制代码
<script>
export default {
  data() {
    return {
      count: 0
    }
  }
}
</script>

<template>
  <button @click="count++">You clicked me {{ count }} times.</button>
</template>

然后在父组件中引入并使用它:

vue 复制代码
<script>
import ButtonCounter from './ButtonCounter.vue'

export default {
  components: {
    ButtonCounter
  }
}
</script>

<template>
  <h1>Here is a child component!</h1>
  <ButtonCounter />
</template>

组件拆分的关键不是"越细越好",而是看它是否具备复用价值、是否能让当前页面更容易维护。

6. props:父组件向子组件传值

父组件向子组件传递数据,最常用的方式是 props

子组件 BlogPost.vue

vue 复制代码
<script>
export default {
  props: ['title']
}
</script>

<template>
  <h4>{{ title }}</h4>
</template>

父组件:

vue 复制代码
<script>
import BlogPost from './BlogPost.vue'

export default {
  components: {
    BlogPost
  },
  data() {
    return {
      posts: [
        { id: 1, title: 'My journey with Vue' },
        { id: 2, title: 'Blogging with Vue' },
        { id: 3, title: 'Why Vue is so fun' }
      ]
    }
  }
}
</script>

<template>
  <BlogPost
    v-for="post in posts"
    :key="post.id"
    :title="post.title"
  />
</template>

这里的 :title="post.title" 表示把父组件中的 post.title 动态传给子组件的 title 属性。

7. 子组件通知父组件:优先使用 emit

有些初学者会在子组件里通过 this.$parent 直接调用父组件方法。虽然这种方式能运行,但不推荐长期使用,因为它会让父子组件强耦合,后续维护成本较高。

更推荐的方式是:子组件通过 $emit 抛出事件,父组件监听事件并处理业务逻辑。

子组件:

vue 复制代码
<template>
  <button @click="handleClick">点击</button>
</template>

<script>
export default {
  methods: {
    handleClick() {
      this.$emit('confirm')
    }
  }
}
</script>

父组件:

vue 复制代码
<template>
  <Child @confirm="fatherMethod" />
</template>

<script>
import Child from './Child.vue'

export default {
  components: {
    Child
  },
  methods: {
    fatherMethod() {
      console.log('测试')
    }
  }
}
</script>

这种写法更符合 Vue 的单向数据流:父组件通过 props 给子组件传值,子组件通过事件通知父组件。

8. 生命周期:在合适的阶段执行代码

生命周期钩子用于在组件不同阶段执行代码。以 mounted 为例,它会在组件完成初始渲染并创建 DOM 节点后执行。

vue 复制代码
export default {
  mounted() {
    console.log('the component is now mounted.')
  }
}

常见使用场景包括:

  • 组件挂载后请求接口数据。
  • 初始化依赖 DOM 的第三方库。
  • 读取页面元素尺寸。
  • 注册事件监听,并在组件卸载时清理。

如果需要查看完整生命周期,可以参考 Vue 官方文档:

https://cn.vuejs.org/api/options-lifecycle.html

9. 小结

本文梳理了 Vue3 进阶阶段最常见的几个知识点:

  • 选项式 API 用于组织组件状态、方法、计算属性和生命周期。
  • 单文件组件让结构、逻辑和样式拥有清晰边界。
  • createAppmount 是 Vue 应用启动的入口。
  • v-model 可以简化表单双向绑定。
  • 组件拆分能提升复用性和可维护性。
  • props 用于父传子,emit 用于子通知父。
  • 生命周期钩子适合处理组件不同阶段的副作用逻辑。

掌握这些内容后,再去学习组合式 API、Pinia、Vue Router、组件封装和工程化实践,会顺畅很多。Vue3 的学习重点不是记住每个 API,而是理解组件之间如何协作,以及状态如何驱动视图更新。