您好,欢迎来到12图资源库!分享精神,快乐你我!我们只是素材的搬运工!!
  • 首 页
  • 当前位置:首页 > 开发 > WEB开发 >
    Vue 3 的组合 API 如何央求数据?(2)
    时间:2020-10-20 12:04 来源:网络整理 作者:网络 浏览:收藏 挑错 推荐 打印

    我们将 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 形状:


    Demo

    将数据央求逻辑笼统

    用过 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 还有两个缺陷:

    1.传入的 url 是固定的,query 修正后,不能及时的反响到 url 上;

    2.不能自动央求,需求手动调用一下 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, 

        } 

      } 

    当然,这个 useRequest 还有很多可以完善的中央,例如:不支持 http 办法修正、不支持节流防抖、不支持超时时间等等。最后,希望大家看完文章后能有所播种。

    本文转载自微信群众号「更了不起的前端」,可以经过以下二维码关注。转载本文请联络更了不起的前端群众号。

    【编辑引荐】

    重新思索可继续数据中心设计

    Vue中Axios的封装和API接口的管理

    「算法与数据结构」带你看分治算法之美

    物联网数据智能:打造“及时照应”企业

    SocialBlock:可以改善智慧城市中数据安全的技术

    (责任编辑:admin)