Vue中选项式和组合式API的学习
2026/5/3 7:27:03 网站建设 项目流程

Vue中选项式和组合式API的学习

    • 组合式 API (Composition API)
    • 选项式 API (Options API)
      • export default 的作用
      • data
      • created
      • methods
    • 两种风格对比
    • 在其他 Vue 组件中导入和使用 `export default` 定义的组件 有几种方式
      • 基本导入和使用
      • 调用子组件的方法
      • 完整的父子组件通信示例
      • 关键点总结:

Vue 的组件可以按两种不同的风格书写 :组合式 API和选项式 API 。

组合式 API (Composition API)

通过组合式 API,可以使用导入的 API 函数来描述组件逻辑。在单文件组件中,组合式 API 通常会与

<script setup>import{ref,onMounted}from'vue'// 响应式状态constcount=ref(0)// 用来修改状态、触发更新的函数functionincrement(){count.value++}// 生命周期钩子onMounted(()=>{console.log(`The initial count is${count.value}.`)})</script><template><button @click="increment">Count is:{{count}}</button></template>

选项式 API (Options API)

使用选项式 API,可以用包含多个选项的对象来描述组件的逻辑,例如datamethodsmounted。选项所定义的属性都会暴露在函数内部的this上,它会指向当前的组件实例。

<script>exportdefault{name:'',//`name` 属性标识组件名称components:{//使用 `components` 选项注册子组件}// data() 返回的属性将会成为响应式的状态// 并且暴露在 `this` 上data(){return{// 所有响应式数据在这里定义count:0};},// methods 是一些用来更改状态与触发更新的函数// 它们可以在模板中作为事件处理器绑定methods:{// 所有组件方法在这里定义},// 生命周期钩子会在组件生命周期的各个不同阶段被调用created(){/* 实例创建后 */},mounted(){/* DOM挂载后 */},updated(){/* 数据更新后 */},destroyed(){/* 实例销毁前 */},// 组件注册components:{// 子组件注册}}<script>

export default 的作用

export default是 ES6 模块系统的语法,用于导出模块的默认内容。在 Vue 中,它用于导出一个 Vue 组件配置对象

exportdefault{// 组件配置选项}

当在另一个文件中使用import时,导入的就是这个默认导出的对象。

data

  • 作用:定义组件的响应式数据
  • 必须是函数:返回一个包含数据的对象
  • 为什么是函数:确保每个组件实例都有独立的数据副本,避免数据共享问题
data(){return{newUser:{name:'',email:''},// 创建新用户时的表单数据users:[],// 存储从API获取的用户列表editingUser:null// 当前正在编辑的用户};}

created

  • 生命周期钩子:在组件实例创建完成后立即调用
  • 执行时机:数据观测已建立,但DOM还未挂载
  • 常见用途:初始化数据、调用API
created(){this.fetchUsers();// 组件创建时自动获取用户列表}

methods

  • 作用:定义组件的方法
  • 特点:这些方法可以直接在模板中调用
methods:{// 异步获取用户列表asyncfetchUsers(){try{constresponse=awaitaxios.get('https://api.example.com/users');this.users=response.data;// 更新响应式数据}catch(error){console.error('获取用户列表失败:',error);}}}

两种风格对比

组合式 API 的核心思想是直接在函数作用域内定义响应式状态变量,并将从多个函数中得到的状态组合起来处理复杂问题。这种形式更加自由,也需要对 Vue 的响应式系统有更深的理解才能高效使用。相应的,它的灵活性也使得组织和重用逻辑的模式变得更加强大。

选项式 API 是在组合式 API 的基础上实现的。选项式 API 以“组件实例”的概念为中心 (即上述例子中的this),基于面向对象概念实现。同时,它将响应性相关的细节抽象出来,并强制按照选项来组织代码。

以下是官方给出的建议:

  • 在学习的过程中,推荐采用更易于理解的风格。大部分的核心概念在这两种风格之间都是通用的。熟悉了一种风格以后,也能够很快地理解另一种风格。
  • 在生产项目中:
    • 当不需要使用构建工具,或者打算主要在低复杂度的场景中使用 Vue,例如渐进增强的应用场景,推荐采用选项式 API。
    • 当你打算用 Vue 构建完整的单页应用,推荐采用组合式 API + 单文件组件。

在其他 Vue 组件中导入和使用export default定义的组件 有几种方式

基本导入和使用

导入组件

<template> <div> <!-- 使用导入的组件 --> <ArticleList /> </div> </template> // 选项式 <script> // 导入组件 import ArticleList from '@/components/ArticleList.vue' export default { name: 'ParentComponent', components: { // 注册导入的组件 ArticleList } } </script>

调用子组件的方法

方法一:使用 ref 引用

<template> <div> <button @click="refreshArticles">刷新文章</button> <button @click="createNewArticle">创建文章</button> <!-- 给组件添加 ref 属性 --> <ArticleList ref="articleListRef" /> </div> </template> <script> import ArticleList from '@/components/ArticleList.vue' export default { name: 'ParentComponent', components: { ArticleList }, methods: { refreshArticles() { // 调用子组件的 fetchArticles 方法 this.$refs.articleListRef.fetchArticles() }, createNewArticle() { // 调用子组件的 handleCreateArticle 方法 this.$refs.articleListRef.handleCreateArticle() } } } </script>

方法二:通过 props 传递回调函数

父组件:

<template> <div> <ArticleList :onRefresh="handleRefresh" :onCreate="handleCreate" /> </div> </template> <script> import ArticleList from '@/components/ArticleList.vue' export default { components: { ArticleList }, methods: { handleRefresh() { console.log('父组件处理刷新逻辑') }, handleCreate(articleData) { console.log('父组件处理创建逻辑', articleData) } } } </script>

子组件 (ArticleList.vue):

<script> export default { name: 'ArticleList', props: { onRefresh: Function, onCreate: Function }, methods: { fetchArticles() { // 原有的获取文章逻辑 fetch('http://localhost:8000/posts') .then(r => r.json()) .then(data => { this.articles = data // 如果有传递回调函数,则调用 if (this.onRefresh) { this.onRefresh(data) } }) }, handleCreateArticle() { // 原有的创建逻辑... // 如果有传递回调函数,则调用 if (this.onCreate) { this.onCreate(this.newArticle) } } } } </script>

完整的父子组件通信示例

父组件

<template> <div class="parent"> <h1>博客管理</h1> <div class="controls"> <button @click="triggerRefresh" :disabled="isLoading"> {{ isLoading ? '加载中...' : '刷新文章' }} </button> <button @click="showCreateForm = true">新建文章</button> </div> <!-- 使用子组件 --> <ArticleList ref="articleList" :externalCreateData="createFormData" @articles-loaded="onArticlesLoaded" @article-created="onArticleCreated" /> <!-- 父组件的创建表单 --> <div v-if="showCreateForm" class="modal"> <h3>创建新文章</h3> <input v-model="createFormData.title" placeholder="标题"> <textarea v-model="createFormData.content" placeholder="内容"></textarea> <button @click="submitCreateForm">提交</button> <button @click="cancelCreate">取消</button> </div> </div> </template> <script> import ArticleList from '@/components/ArticleList.vue' export default { name: 'BlogManagement', components: { ArticleList }, data() { return { isLoading: false, showCreateForm: false, createFormData: { title: '', content: '' } } }, methods: { // 触发子组件的刷新方法 triggerRefresh() { this.isLoading = true this.$refs.articleList.fetchArticles() }, // 触发子组件的创建方法 submitCreateForm() { this.$refs.articleList.handleCreateArticle(this.createFormData) this.showCreateForm = false }, cancelCreate() { this.showCreateForm = false this.createFormData = { title: '', content: '' } }, // 监听子组件的事件 onArticlesLoaded(articles) { this.isLoading = false console.log('文章加载完成:', articles) }, onArticleCreated(newArticle) { console.log('新文章创建:', newArticle) this.createFormData = { title: '', content: '' } } } } </script>

子组件 (ArticleList.vue)

<template> <div class="article-list"> <div v-if="articles.length === 0" class="empty">暂无文章</div> <ArticleCard v-for="article in articles" :key="article.id" :article="article" /> </div> </template> <script> import ArticleCard from './ArticleCard.vue' export default { name: 'ArticleList', components: { ArticleCard }, props: { // 从父组件接收创建数据 externalCreateData: { type: Object, default: () => ({ title: '', content: '' }) } }, data() { return { articles: [], newArticle: { title: '', content: '', author: '左越' } } }, watch: { // 监听外部创建数据的变化 externalCreateData: { handler(newData) { if (newData.title || newData.content) { this.newArticle = { ...newData, author: '左越' } this.handleCreateArticle() } }, deep: true } }, created() { this.fetchArticles() }, methods: { async fetchArticles() { try { const response = await fetch('http://localhost:8000/posts') const data = await response.json() this.articles = data // 触发事件通知父组件 this.$emit('articles-loaded', data) } catch (err) { console.log('error', err) this.$emit('articles-loaded', []) } }, async handleCreateArticle(externalData = null) { const articleData = externalData || this.newArticle if (!articleData.title.trim() || !articleData.content.trim()) { alert('请填写所有字段') return } try { const response = await fetch('http://localhost:8000/posts', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(articleData) }) const newArticle = await response.json() this.articles.unshift(newArticle) // 触发事件通知父组件 this.$emit('article-created', newArticle) // 重置表单 this.resetForm() } catch (err) { console.error('error: ', err) } }, resetForm() { this.newArticle = { title: '', content: '', author: '左越' } } } } </script>

关键点总结:

  1. 导入组件:使用import ComponentName from 'path/to/component'
  2. 注册组件:在components选项中注册
  3. 使用 ref:通过this.$refs.refName.methodName()调用子组件方法
  4. 事件通信:子组件使用this.$emit('event-name', data),父组件使用@event-name="handler"
  5. Props 传递:父组件通过 props 向子组件传递数据和方法

选择哪种方式取决于具体需求:

  • 简单的调用使用ref
  • 复杂的通信使用propsevents
  • 状态管理考虑使用 Vuex(对于大型应用)

这种结构让 Vue 能够自动处理数据与视图的同步,大大简化了前端开发的复杂度。


愿你我都能在各自的领域里不断成长,勇敢追求梦想,同时也保持对世界的好奇与善意!

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询