中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Vue 3的組合API怎么請求數據

發布時間:2021-10-26 11:18:41 來源:億速云 閱讀:202 作者:iii 欄目:web開發

這篇文章主要講解了“Vue 3的組合API怎么請求數據”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“Vue 3的組合API怎么請求數據”吧!

項目初始化
為了快速啟動一個 Vue 3 項目,我們直接使用當下最熱門的工具 Vite 來初始化項目。整個過程一氣呵成,行云流水。

npm init vite-app vue3-app
# 打開生成的項目文件夾 cd vue3-app # 安裝依賴 npm install # 啟動項目 npm run dev

我們打開 App.vue 將生成的代碼先刪掉。

組合 API 的入口
接下來我們將通過 Hacker News API 來獲取一些熱門文章,Hacker News API返回的數據結構如下:

{   "hits": [     {       "objectID": "24518295",       "title": "Vue.js 3",       "url": "https://github.com/vuejs/vue-next/releases/tag/v3.0.0",     },     {...},     {...},   ] }

我們通過 ui > li 將新聞列表展示到界面上,新聞數據從 hits 遍歷中獲取

<template>   <ul>     <li       v-for="item of hits"       :key="item.objectID"     >       <a :href="item.url">{{item.title}}</a>     </li>   </ul> </template>  <script> import { reactive } from 'vue'  export default {   setup() {     const state = reactive({       hits: []     })     return state   } } </script>

在講解數據請求前,我看先看看 setup() 方法,組合 API 需要通過 setup() 方法來啟動,setup() 返回的數據可以在模板內使用,可以簡單理解為 Vue 2 里面 data() 方法返回的數據,不同的是,返回的數據需要先經過 reactive() 方法進行包裹,將數據變成響應式。

組合 API 中請求數據
在 Vue 2 中,我們請求數據時,通常需要將發起請求的代碼放到某個生命周期中(created 或 mounted)。在 setup() 方法內,我們可以使用 Vue 3 提供的生命周期鉤子將請求放到特定生命周期內,關于生命周期鉤子方法與之前生命周期的對比如下:

Vue 3的組合API怎么請求數據

生命周期

可以看到,基本上就是在之前的方法名前加上了一個 on,且并沒有提供 onCreated 的鉤子,因為在 setup() 內執行就相當于在 created 階段執行。下面我們在 mounted 階段來請求數據:

import { reactive, onMounted } from 'vue'  export default {   setup() {     const state = reactive({       hits: []     })     onMounted(async () => {       const data = await fetch(         'https://hn.algolia.com/api/v1/search?query=vue'       ).then(rsp => rsp.json())       state.hits = data.hits     })     return state   } }

最后效果如下:

Vue 3的組合API怎么請求數據

監聽數據變動
Hacker News 的查詢接口有一個 query 參數,前面的案例中,我們將這個參數固定了,現在我們通過響應式的數據來定義這個變量。

<template>   <input type="text" v-model="query" />   <ul>     <li       v-for="item of hits"       :key="item.objectID"     >       <a :href="item.url">{{item.title}}</a>     </li>   </ul> </template>  <script> import { reactive, onMounted } from 'vue'  export default {   setup() {     const state = reactive({       query: 'vue',       hits: []     })     onMounted((async () => {       const data = await fetch(         `https://hn.algolia.com/api/v1/search?query=${state.query}`       ).then(rsp => rsp.json())       state.hits = data.hits     })     return state   } } </script>

現在我們在輸入框修改,就能觸發 state.query 同步更新,但是并不會觸發 fetch 重新調用,所以我們需要通過 watchEffect() 來監聽響應數據的變化。

import { reactive, onMounted, watchEffect } from 'vue'  export default {   setup() {     const state = reactive({       query: 'vue',       hits: []     })     const fetchData = async (query) => {       const data = await fetch(         `https://hn.algolia.com/api/v1/search?query=${query}`       ).then(rsp => rsp.json())       state.hits = data.hits     }     onMounted(() => {       fetchData(state.query)       watchEffect(() => {         fetchData(state.query)       })     })     return state   } }

由于 watchEffect() 首次調用的時候,其回調就會執行一次,造成初始化時會請求兩次接口,所以我們需要把 onMounted 中的 fetchData 刪掉。

onMounted(() => { - fetchData(state.query)   watchEffect(() => {     fetchData(state.query)   }) })

Vue 3的組合API怎么請求數據

watchEffect() 會監聽傳入函數內所有的響應式數據,一旦其中的某個數據發生變化,函數就會重新執行。如果要取消監聽,可以調用 watchEffect() 的返回值,它的返回值為一個函數。下面舉個例子:

const stop = watchEffect(() => {   if (state.query === 'vue3') {     // 當 query 為 vue3 時,停止監聽     stop()   }   fetchData(state.query) })

當我們在輸入框輸入 "vue3" 后,就不會再發起請求了。

Vue 3的組合API怎么請求數據

返回事件方法
現在有個問題就是 input 內的值每次修改都會觸發一次請求,我們可以增加一個按鈕,點擊按鈕后再觸發 state.query 的更新。

<template>   <input type="text" v-model="input" />   <button @click="setQuery">搜索</button>   <ul>     <li       v-for="item of hits"       :key="item.objectID"     >       <a :href="item.url">{{item.title}}</a>     </li>   </ul> </template>  <script> import { reactive, onMounted, watchEffect } from 'vue'  export default {   setup() {     const state = reactive({       input: 'vue',       query: 'vue',       hits: []     })     const fetchData = async (query) => {       const data = await fetch(         `https://hn.algolia.com/api/v1/search?query=${query}`       ).then(rsp => rsp.json())       state.hits = data.hits     }     onMounted(() => {       watchEffect(() => {         fetchData(state.query)       })     })          const setQuery = () => {       state.query = state.input     }     return { setQuery, state }   } } </script>

可以注意到 button 綁定的 click 事件的方法,也是通過 setup() 方法返回的,我們可以將 setup() 方法返回值理解為 Vue2 中 data() 方法和 methods 對象的合并。

原先的返回值 state 變成了現在返回值的一個屬性,所以我們在模板層取數據的時候,需要進行一些修改,在前面加上 state.。

<template>   <input type="text" v-model="state.input" />   <button @click="setQuery">搜索</button>   <ul>     <li       v-for="item of state.hits"       :key="item.objectID"     >       <a :href="item.url">{{item.title}}</a>     </li>   </ul> </template>

Vue 3的組合API怎么請求數據

返回數據修改
作為強迫癥患者,在模板層通過 state.xxx 的方式獲取數據實在是難受,那我們是不是可以通過對象解構的方式將 state 的數據返回呢?

<template>   <input type="text" v-model="input" />   <button class="search-btn" @click="setQuery">搜索</button>   <ul class="results">     <li       v-for="item of hits"       :key="item.objectID"     >       <a :href="item.url">{{item.title}}</a>     </li>   </ul> </template>  <script> import { reactive, onMounted, watchEffect } from 'vue'  export default {   setup(props, ctx) {     const state = reactive({       input: 'vue',       query: 'vue',       hits: []     })     // 省略部分代碼...     return {       ...state,       setQuery,     }   } } </script>

答案是『不可以』。修改代碼后,可以看到頁面雖然發起了請求,但是頁面并沒有展示數據。

state 在解構后,數據就變成了靜態數據,不能再被跟蹤,返回值類似于:

export default {   setup(props, ctx) {     // 省略部分代碼...     return {       input: 'vue',       query: 'vue',       hits: [],       setQuery,     }   } }

Vue 3的組合API怎么請求數據

為了跟蹤基礎類型的數據(即非對象數據),Vue3 也提出了解決方案:ref() 。

import { ref } from 'vue'  const count = ref(0) console.log(count.value) // 0  count.value++ console.log(count.value) // 1

上面為 Vue 3 的官方案例,ref() 方法返回的是一個對象,無論是修改還是獲取,都需要取返回對象的 value 屬性。

我們將 state 從響應對象改為一個普通對象,然后所有屬性都使用 ref 包裹,這樣修改后,后續的解構才做才能生效。這樣的弊端就是,state 的每個屬性在修改時,都必須取其 value 屬性。但是在模板中不需要追加 .value,Vue 3 內部有對其進行處理。

import { ref, onMounted, watchEffect } from 'vue' export default {   setup() {     const state = {       input: ref('vue'),       query: ref('vue'),       hits: ref([])     }     const fetchData = async (query) => {       const data = await fetch(         `https://hn.algolia.com/api/v1/search?query=${query}`       ).then(rsp => rsp.json())       state.hits.value = data.hits     }     onMounted(() => {       watchEffect(() => {         fetchData(state.query.value)       })     })     const setQuery = () => {       state.query.value = state.input.value     }     return {       ...state,       setQuery,     }   } }

有沒有辦法保持 state 為響應對象,同時又支持其對象解構的呢?當然是有的,Vue 3 也提供了解決方案:toRefs() 。toRefs() 方法可以將一個響應對象變為普通對象,并且給每個屬性加上 ref()。

import { toRefs, reactive, onMounted, watchEffect } from 'vue'  export default {   setup() {     const state = reactive({       input: 'vue',       query: 'vue',       hits: []     })     const fetchData = async (query) => {       const data = await fetch(         `https://hn.algolia.com/api/v1/search?query=${query}`       ).then(rsp => rsp.json())       state.hits = data.hits     }     onMounted(() => {       watchEffect(() => {         fetchData(state.query)       })     })     const setQuery = () => {       state.query = state.input     }     return {       ...toRefs(state),       setQuery,     }   } }

Loading 與 Error 狀態
通常,我們發起請求的時候,需要為請求添加 Loading 和 Error 狀態,我們只需要在 state 中添加兩個變量來控制這兩種狀態即可。

export default {   setup() {     const state = reactive({       input: 'vue',       query: 'vue',       hits: [],       error: false,       loading: false,     })     const fetchData = async (query) => {       state.error = false       state.loading = true       try {         const data = await fetch(           `https://hn.algolia.com/api/v1/search?query=${query}`         ).then(rsp => rsp.json())         state.hits = data.hits       } catch {         state.error = true       }       state.loading = false     }     onMounted(() => {       watchEffect(() => {         fetchData(state.query)       })     })     const setQuery = () => {       state.query = state.input     }     return {       ...toRefs(state),       setQuery,     }   } }

同時在模板使用這兩個變量:

<template>   <input type="text" v-model="input" />   <button @click="setQuery">搜索</button>   <div v-if="loading">Loading ...</div>   <div v-else-if="error">Something went wrong ...</div>   <ul v-else>     <li       v-for="item of hits"       :key="item.objectID"     >       <a :href="item.url">{{item.title}}</a>     </li>   </ul> </template>

展示 Loading、Error 狀態:

Vue 3的組合API怎么請求數據

將數據請求邏輯抽象
用過 umi 的同學肯定知道 umi 提供了一個叫做 useRequest 的 Hooks,用于請求數據非常的方便,那么我們通過 Vue 的組合 API 也可以抽象出一個類似于 useRequest 的公共方法。

接下來我們新建一個文件 useRequest.js :

import {   toRefs,   reactive, } from 'vue'  export default (options) => {   const { url } = options   const state = reactive({     data: {},     error: false,     loading: false,   })    const run = async () => {     state.error = false     state.loading = true     try {       const result = await fetch(url).then(res => res.json())       state.data = result     } catch(e) {       state.error = true     }     state.loading = false   }    return {     run,     ...toRefs(state)   } }

然后在 App.vue 中引入:

<template>   <input type="text" v-model="query" />   <button @click="search">搜索</button>   <div v-if="loading">Loading ...</div>   <div v-else-if="error">Something went wrong ...</div>   <ul v-else>     <li       v-for="item of data.hits"       :key="item.objectID"     >       <a :href="item.url">{{item.title}}</a>     </li>   </ul> </template>  <script> import { ref, onMounted } from 'vue' import useRequest from './useRequest'  export default {   setup() {     const query = ref('vue')     const { data, loading, error, run } = useRequest({       url: 'https://hn.algolia.com/api/v1/search'     })     onMounted(() => {       run()     })     return {       data,       query,       error,       loading,       search: run,     }   } } </script>

當前的 useRequest 還有兩個缺陷:

傳入的 url 是固定的,query 修改后,不能及時的反應到 url 上;
不能自動請求,需要手動調用一下 run 方法;

import {   isRef,   toRefs,   reactive,   onMounted, } from 'vue'  export default (options) => {   const { url, manual = false, params = {} } = options    const state = reactive({     data: {},     error: false,     loading: false,   })    const run = async () => {     // 拼接查詢參數     let query = ''     Object.keys(params).forEach(key => {       const val = params[key]       // 如果去 ref 對象,需要取 .value 屬性       const value = isRef(val) ? val.value : val       query += `${key}=${value}&`     })     state.error = false     state.loading = true     try {       const result = await fetch(`${url}?${query}`)        .then(res => res.json())       state.data = result     } catch(e) {       state.error = true     }     state.loading = false   }    onMounted(() => {     // 第一次是否需要手動調用     !manual && run()   })    return {     run,     ...toRefs(state)   } }

經過修改后,我們的邏輯就變得異常簡單了。

import useRequest from './useRequest'  export default {   setup() {     const query = ref('vue')     const { data, loading, error, run } = useRequest(       {         url: 'https://hn.algolia.com/api/v1/search',         params: {           query         }       }     )     return {       data,       query,       error,       loading,       search: run,     }   } }

感謝各位的閱讀,以上就是“Vue 3的組合API怎么請求數據”的內容了,經過本文的學習后,相信大家對Vue 3的組合API怎么請求數據這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

阿拉善右旗| 潮安县| 四平市| 阿图什市| 山丹县| 萨嘎县| 太白县| 陆良县| 宾阳县| 科技| 芦溪县| 扎赉特旗| 咸阳市| 昌邑市| 滁州市| 兴义市| 澜沧| 乌拉特中旗| 阿瓦提县| 义乌市| 津市市| 钦州市| 凤庆县| 水城县| 孟村| 开远市| 涪陵区| 米泉市| 道真| 北京市| 墨竹工卡县| 岳普湖县| 巧家县| 庆云县| 大石桥市| 河北区| 安康市| 青冈县| 商南县| 怀来县| 晋江市|