最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue中選項(xiàng)式和組合式API的使用詳解

 更新時(shí)間:2025年12月16日 10:53:30   作者:鈍挫力PROGRAMER  
本文介紹了Vue.js中的兩種主要API風(fēng)格:選項(xiàng)式API和組合式API,選項(xiàng)式API通過(guò)在單文件組件中使用,本文結(jié)合實(shí)例代碼對(duì)每種方式給大家詳細(xì)講解,感興趣的朋友跟隨小編一起看看吧

Vue 的組件可以按兩種不同的風(fēng)格書(shū)寫(xiě) :組合式 API和選項(xiàng)式 API 。

組合式 API (Composition API)

通過(guò)組合式 API,可以使用導(dǎo)入的 API 函數(shù)來(lái)描述組件邏輯。在單文件組件中,組合式 API 通常會(huì)與

<script setup>
import { ref, onMounted } from 'vue'
// 響應(yīng)式狀態(tài)
const count = ref(0)
// 用來(lái)修改狀態(tài)、觸發(fā)更新的函數(shù)
function increment() {
  count.value++
}
// 生命周期鉤子
onMounted(() => {
  console.log(`The initial count is ${count.value}.`)
})
</script>
<template>
  <button @click="increment">Count is: {{ count }}</button>
</template>

選項(xiàng)式 API (Options API)

使用選項(xiàng)式 API,可以用包含多個(gè)選項(xiàng)的對(duì)象來(lái)描述組件的邏輯,例如 data、methodsmounted。選項(xiàng)所定義的屬性都會(huì)暴露在函數(shù)內(nèi)部的 this 上,它會(huì)指向當(dāng)前的組件實(shí)例。

<script>
    export default {
	  name: '',  //`name` 屬性標(biāo)識(shí)組件名稱
      components: { //使用 `components` 選項(xiàng)注冊(cè)子組件 
       }
       // data() 返回的屬性將會(huì)成為響應(yīng)式的狀態(tài)
       // 并且暴露在 `this` 上
      data() {
        return {
          // 所有響應(yīng)式數(shù)據(jù)在這里定義
          count: 0
        };
      },
      // methods 是一些用來(lái)更改狀態(tài)與觸發(fā)更新的函數(shù)
      // 它們可以在模板中作為事件處理器綁定
      methods: {
        // 所有組件方法在這里定義
      },
      // 生命周期鉤子會(huì)在組件生命周期的各個(gè)不同階段被調(diào)用
      created() { /* 實(shí)例創(chuàng)建后 */ },
      mounted() { /* DOM掛載后 */ },
      updated() { /* 數(shù)據(jù)更新后 */ },
      destroyed() { /* 實(shí)例銷毀前 */ },
      // 組件注冊(cè)
      components: {
        // 子組件注冊(cè)
      }
    }
<script>

export default 的作用

export default 是 ES6 模塊系統(tǒng)的語(yǔ)法,用于導(dǎo)出模塊的默認(rèn)內(nèi)容。在 Vue 中,它用于導(dǎo)出一個(gè) Vue 組件配置對(duì)象

export default {
  // 組件配置選項(xiàng)
}

當(dāng)在另一個(gè)文件中使用 import 時(shí),導(dǎo)入的就是這個(gè)默認(rèn)導(dǎo)出的對(duì)象。

data

  • 作用:定義組件的響應(yīng)式數(shù)據(jù)
  • 必須是函數(shù):返回一個(gè)包含數(shù)據(jù)的對(duì)象
  • 為什么是函數(shù):確保每個(gè)組件實(shí)例都有獨(dú)立的數(shù)據(jù)副本,避免數(shù)據(jù)共享問(wèn)題
data() {
  return {
    newUser: { name: '', email: '' },  // 創(chuàng)建新用戶時(shí)的表單數(shù)據(jù)
    users: [],                         // 存儲(chǔ)從API獲取的用戶列表
    editingUser: null                  // 當(dāng)前正在編輯的用戶
  };
}

created

  • 生命周期鉤子:在組件實(shí)例創(chuàng)建完成后立即調(diào)用
  • 執(zhí)行時(shí)機(jī):數(shù)據(jù)觀測(cè)已建立,但DOM還未掛載
  • 常見(jiàn)用途:初始化數(shù)據(jù)、調(diào)用API
created() {
  this.fetchUsers(); // 組件創(chuàng)建時(shí)自動(dòng)獲取用戶列表
}

methods

  • 作用:定義組件的方法
  • 特點(diǎn):這些方法可以直接在模板中調(diào)用
methods: {
  // 異步獲取用戶列表
  async fetchUsers() {
    try {
      const response = await axios.get('https://api.example.com/users');
      this.users = response.data; // 更新響應(yīng)式數(shù)據(jù)
    } catch (error) {
      console.error('獲取用戶列表失敗:', error);
    }
  }
}

兩種風(fēng)格對(duì)比

組合式 API 的核心思想是直接在函數(shù)作用域內(nèi)定義響應(yīng)式狀態(tài)變量,并將從多個(gè)函數(shù)中得到的狀態(tài)組合起來(lái)處理復(fù)雜問(wèn)題。這種形式更加自由,也需要對(duì) Vue 的響應(yīng)式系統(tǒng)有更深的理解才能高效使用。相應(yīng)的,它的靈活性也使得組織和重用邏輯的模式變得更加強(qiáng)大。

選項(xiàng)式 API 是在組合式 API 的基礎(chǔ)上實(shí)現(xiàn)的。選項(xiàng)式 API 以“組件實(shí)例”的概念為中心 (即上述例子中的 this),基于面向?qū)ο蟾拍顚?shí)現(xiàn)。同時(shí),它將響應(yīng)性相關(guān)的細(xì)節(jié)抽象出來(lái),并強(qiáng)制按照選項(xiàng)來(lái)組織代碼。

以下是官方給出的建議:

  • 在學(xué)習(xí)的過(guò)程中,推薦采用更易于理解的風(fēng)格。大部分的核心概念在這兩種風(fēng)格之間都是通用的。熟悉了一種風(fēng)格以后,也能夠很快地理解另一種風(fēng)格。
  • 在生產(chǎn)項(xiàng)目中:
    • 當(dāng)不需要使用構(gòu)建工具,或者打算主要在低復(fù)雜度的場(chǎng)景中使用 Vue,例如漸進(jìn)增強(qiáng)的應(yīng)用場(chǎng)景,推薦采用選項(xiàng)式 API。
    • 當(dāng)你打算用 Vue 構(gòu)建完整的單頁(yè)應(yīng)用,推薦采用組合式 API + 單文件組件。

在其他 Vue 組件中導(dǎo)入和使用export default定義的組件 有幾種方式

基本導(dǎo)入和使用

導(dǎo)入組件

<template>
  <div>
    <!-- 使用導(dǎo)入的組件 -->
    <ArticleList />
  </div>
</template>
// 選項(xiàng)式
<script>
// 導(dǎo)入組件
import ArticleList from '@/components/ArticleList.vue'
export default {
  name: 'ParentComponent',
  components: {
    // 注冊(cè)導(dǎo)入的組件
    ArticleList
  }
}
</script>

調(diào)用子組件的方法

方法一:使用 ref 引用

<template>
  <div>
    <button @click="refreshArticles">刷新文章</button>
    <button @click="createNewArticle">創(chuàng)建文章</button>
    <!-- 給組件添加 ref 屬性 -->
    <ArticleList ref="articleListRef" />
  </div>
</template>
<script>
import ArticleList from '@/components/ArticleList.vue'
export default {
  name: 'ParentComponent',
  components: {
    ArticleList
  },
  methods: {
    refreshArticles() {
      // 調(diào)用子組件的 fetchArticles 方法
      this.$refs.articleListRef.fetchArticles()
    },
    createNewArticle() {
      // 調(diào)用子組件的 handleCreateArticle 方法
      this.$refs.articleListRef.handleCreateArticle()
    }
  }
}
</script>

方法二:通過(guò) props 傳遞回調(diào)函數(shù)

父組件:

<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('父組件處理創(chuàng)建邏輯', 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
          // 如果有傳遞回調(diào)函數(shù),則調(diào)用
          if (this.onRefresh) {
            this.onRefresh(data)
          }
        })
    },
    handleCreateArticle() {
      // 原有的創(chuàng)建邏輯...
      // 如果有傳遞回調(diào)函數(shù),則調(diào)用
      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"
    />
    <!-- 父組件的創(chuàng)建表單 -->
    <div v-if="showCreateForm" class="modal">
      <h3>創(chuàng)建新文章</h3>
      <input v-model="createFormData.title" placeholder="標(biāo)題">
      <textarea v-model="createFormData.content" placeholder="內(nèi)容"></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: {
    // 觸發(fā)子組件的刷新方法
    triggerRefresh() {
      this.isLoading = true
      this.$refs.articleList.fetchArticles()
    },
    // 觸發(fā)子組件的創(chuàng)建方法
    submitCreateForm() {
      this.$refs.articleList.handleCreateArticle(this.createFormData)
      this.showCreateForm = false
    },
    cancelCreate() {
      this.showCreateForm = false
      this.createFormData = { title: '', content: '' }
    },
    // 監(jiān)聽(tīng)子組件的事件
    onArticlesLoaded(articles) {
      this.isLoading = false
      console.log('文章加載完成:', articles)
    },
    onArticleCreated(newArticle) {
      console.log('新文章創(chuàng)建:', newArticle)
      this.createFormData = { title: '', content: '' }
    }
  }
}
</script>

子組件 (ArticleList.vue)

<template>
  <div class="article-list">
    <div v-if="articles.length === 0" class="empty">暫無(wú)文章</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: {
    // 從父組件接收創(chuàng)建數(shù)據(jù)
    externalCreateData: {
      type: Object,
      default: () => ({ title: '', content: '' })
    }
  },
  data() {
    return {
      articles: [],
      newArticle: {
        title: '',
        content: '',
        author: '左越'
      }
    }
  },
  watch: {
    // 監(jiān)聽(tīng)外部創(chuàng)建數(shù)據(jù)的變化
    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
        // 觸發(fā)事件通知父組件
        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('請(qǐng)?zhí)顚?xiě)所有字段')
        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)
        // 觸發(fā)事件通知父組件
        this.$emit('article-created', newArticle)
        // 重置表單
        this.resetForm()
      } catch (err) {
        console.error('error: ', err)
      }
    },
    resetForm() {
      this.newArticle = {
        title: '',
        content: '',
        author: '左越'
      }
    }
  }
}
</script>

關(guān)鍵點(diǎn)總結(jié):

  1. 導(dǎo)入組件:使用 import ComponentName from 'path/to/component'
  2. 注冊(cè)組件:在 components 選項(xiàng)中注冊(cè)
  3. 使用 ref:通過(guò) this.$refs.refName.methodName() 調(diào)用子組件方法
  4. 事件通信:子組件使用 this.$emit('event-name', data),父組件使用 @event-name="handler"
  5. Props 傳遞:父組件通過(guò) props 向子組件傳遞數(shù)據(jù)和方法

選擇哪種方式取決于具體需求:

  • 簡(jiǎn)單的調(diào)用使用 ref
  • 復(fù)雜的通信使用 propsevents
  • 狀態(tài)管理考慮使用 Vuex(對(duì)于大型應(yīng)用)

這種結(jié)構(gòu)讓 Vue 能夠自動(dòng)處理數(shù)據(jù)與視圖的同步,大大簡(jiǎn)化了前端開(kāi)發(fā)的復(fù)雜度。

愿你我都能在各自的領(lǐng)域里不斷成長(zhǎng),勇敢追求夢(mèng)想,同時(shí)也保持對(duì)世界的好奇與善意!

到此這篇關(guān)于Vue中選項(xiàng)式和組合式API的學(xué)習(xí)的文章就介紹到這了,更多相關(guān)vue選項(xiàng)式和組合式API內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

敦煌市| 腾冲县| 高要市| 兴和县| 洪湖市| 涞水县| 中宁县| 泾源县| 孟村| 固始县| 清丰县| 左云县| 长春市| 大荔县| 宜川县| 淮安市| 奉化市| 离岛区| 崇阳县| 龙泉市| 开原市| 博兴县| 凤城市| 通化县| 丁青县| 县级市| 金乡县| 珠海市| 启东市| 柳江县| 兴宁市| 柳林县| 南康市| 瑞丽市| 呼伦贝尔市| 绥中县| 威海市| 固原市| 芜湖县| 岗巴县| 偃师市|