Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

🕶 Data fetching with Vue Composition API. Power of conditions to easily control and sync to the URL query string.

License

NotificationsYou must be signed in to change notification settings

runkids/vue-condition-watcher

Repository files navigation

English |中文

vue-condition-watcher

CircleCIvue3vue3npmnpmbundle sizenpm

Introduction

vue-condition-watcher is a data fetching library using the Vue Composition API. It allows you to easily control and sync data fetching to the URL query string using conditions.

requires Node.js 12.0.0 or higher.

Features

✔ Automatically fetches data when conditions change.✔ Filters out null, undefined, [], and '' before sending requests.✔ Initializes conditions based on URL query strings and syncs them accordingly.✔ Synchronizes URL query strings with condition changes, maintaining normal navigation.✔ Ensures requests are first in, first out, and avoids repeats.✔ Handles dependent requests before updating data.✔ Customizable paging logic.✔ Refetches data when the page is refocused or network resumes.✔ Supports polling with adjustable periods.Caches data for faster rendering.✔ Allows manual data modifications to improve user experience.✔ TypeScript support.✔ Compatible with Vue 2 & 3 viavue-demi.

Navigation

Demo

👉 Download Vue3 example

cd examples/vue3yarn yarn serve

👉 Download Vue2 example

cd examples/vue2yarn yarn serve

👉 Online demo with Vue 3

Installation

yarn add vue-condition-watcher

or

npm install vue-condition-watcher

or via CDN

<scriptsrc="https://unpkg.com/vue-condition-watcher/dist/index.js"></script>

Quick Start


Example usingaxios andvue-router:

<scriptsetup>importaxiosfrom'axios'import{useRouter}from'vue-router'import{useConditionWatcher}from'vue-condition-watcher'constfetcher=params=>axios.get('/user/',{params})constrouter=useRouter()const{ conditions, data, loading, execute, error}=useConditionWatcher({  fetcher,conditions:{name:''},history:{sync:router}})</script><template><divclass="filter"><inputv-model="conditions.name"><button@click="execute">Refetch</button></div><divclass="container">    {{ !loading ? data : 'Loading...' }}</div><divv-if="error">{{ error }}</div></template>

Configs


  • fetcher (required): Function for data fetching.
  • conditions (required): Default conditions.
  • defaultParams: Parameters preset with each request.
  • initialData: Initial data returned.
  • immediate: If false, data will not be fetched initially.
  • manual: If true, fetch requests are manual.
  • history: Syncs conditions with URL query strings using vue-router.
  • pollingInterval: Enables polling with adjustable intervals.
  • pollingWhenHidden: Continues polling when the page loses focus.
  • pollingWhenOffline: Continues polling when offline.
  • revalidateOnFocus: Refetches data when the page regains focus.
  • cacheProvider: Customizable cache provider.
  • beforeFetch: Modify conditions before fetching.
  • afterFetch: Adjust data before updating.
  • onFetchError: Handle fetch errors.

Return Values


  • conditions: Reactive object for conditions.
  • data: Readonly data returned by fetcher.
  • error: Readonly fetch error.
  • isFetching: Readonly fetch status.
  • loading: true when data and error are null.
  • execute: Function to trigger a fetch request.
  • mutate: Function to modify data.
  • resetConditions: Resets conditions to initial values.
  • onConditionsChange: Event triggered on condition changes.
  • onFetchSuccess: Event triggered on successful fetch.
  • onFetchError: Event triggered on fetch error.
  • onFetchFinally: Event triggered when fetch ends.

Execute Fetch


Fetch data whenconditions change:

const{ conditions}=useConditionWatcher({  fetcher,conditions:{page:0},defaultParams:{opt_expand:'date'}})conditions.page=1conditions.page=2

Manually trigger a fetch:

const{ conditions,execute:refetch}=useConditionWatcher({  fetcher,conditions:{page:0},defaultParams:{opt_expand:'date'}})refetch()

Force reset conditions:

const{ conditions, resetConditions}=useConditionWatcher({const{ conditions, resetConditions}=useConditionWatcher({  fetcher,immediate:false,conditions:{page:0,name:'',date:[]},})resetConditions({name:'runkids',date:['2022-01-01','2022-01-02']})

Prevent Request


Prevent requests until execute is called:

const{ execute}=useConditionWatcher({  fetcher,  conditions,immediate:false,})execute()

Manually Trigger Request


Disable automatic fetch and use execute() to trigger:

const{ execute}=useConditionWatcher({  fetcher,  conditions,manual:true,})execute()

Intercepting Request


Modify conditions before fetch:

useConditionWatcher({  fetcher,conditions:{date:['2022/01/01','2022/01/02']},initialData:[],asyncbeforeFetch(conds,cancel){awaitcheckToken()const{ date, ...baseConditions}=condsconst[after,before]=datebaseConditions.created_at_after=afterbaseConditions.created_at_before=beforereturnbaseConditions}})

Modify data after fetch:

const{ data}=useConditionWatcher({  fetcher,  conditions,asyncafterFetch(response){if(response.data===null){return[]}constfinalResponse=awaitotherAPIById(response.data.id)returnfinalResponse}})

Handle fetch errors:

const{ data, error}=useConditionWatcher({  fetcher,  conditions,asynconFetchError({data, error}){if(error.code===401){awaitdoSomething()}return{data:[],error:'Error Message'}}})

Mutations data


Update data using mutate function:

mutate(newData)

Update part of data:

constfinalData=mutate(draft=>{draft[0].name='runkids'returndraft})

🏄‍♂️ Example for updating part of data

const{ conditions, data, mutate}=useConditionWatcher({fetcher:api.userInfo,  conditions,initialData:[]})asyncfunctionupdateUserName(userId,newName,rowIndex=0){constresponse=awaitapi.updateUer(userId,newName)mutate(draft=>{draft[rowIndex]=response.datareturndraft})}

Conditions Change Event


Handle condition changes:

const{ conditions, onConditionsChange}=useConditionWatcher({  fetcher,conditions:{page:0},})conditions.page=1onConditionsChange((conditions,preConditions)=>{console.log(conditions)console.log(preConditions)})

Fetch Event


Handle fetch events:

const{ onFetchResponse, onFetchError, onFetchFinally}=useConditionWatcher(config)onFetchResponse(response=>console.log(response))onFetchError(error=>console.error(error))onFetchFinally(()=>{//todo})

Polling


Enable polling:

useConditionWatcher({  fetcher,  conditions,pollingInterval:1000})

Use ref for reactivity:

constpollingInterval=ref(0)useConditionWatcher({  fetcher,  conditions,pollingInterval:pollingInterval})onMounted(()=>pollingInterval.value=1000)

Continue polling when hidden or offline:

useConditionWatcher({  fetcher,  conditions,pollingInterval:1000,pollingWhenHidden:true,// pollingWhenHidden default is falsepollingWhenOffline:true,// pollingWhenOffline default is falserevalidateOnFocus:true// revalidateOnFocus default is false})

Cache


Cache data globally:

// App.vueconstcache=newMap()exportdefault{name:'App',provide:{cacheProvider:()=>cache}}useConditionWatcher({  fetcher,  conditions,cacheProvider:inject('cacheProvider')})

Cache data inlocalStorage:

functionlocalStorageProvider(){constmap=newMap(JSON.parse(localStorage.getItem('your-cache-key')||'[]'))window.addEventListener('beforeunload',()=>{constappCache=JSON.stringify(Array.from(map.entries()))localStorage.setItem('your-cache-key',appCache)})returnmap}useConditionWatcher({  fetcher,  conditions,cacheProvider:localStorageProvider})

History Mode


Enable history mode usingvue-router:

constrouter=useRouter()useConditionWatcher({  fetcher,  conditions,history:{sync:router}})

Exclude keys from URL query string:

constrouter=useRouter()useConditionWatcher({  fetcher,conditions:{users:['runkids','hello'],limit:20,offset:0},history:{sync:router,ignore:['limit']}})// the query string will be ?offset=0&users=runkids,hello

Convert conditions to query strings:

conditions:{  users:['runkids','hello']  company:''  limit:20,offset:0}// the query string will be ?offset=0&limit=20&users=runkids,hello

Sync query strings to conditions on page refresh:

URL query string: ?offset=0&limit=10&users=runkids,hello&compay=vue

conditions will become

{users:['runkids','hello'],company:'vue',limit:10,offset:0}

Use navigation to replace or push current location:

useConditionWatcher({  fetcher,conditions:{limit:20,offset:0},history:{sync:router,navigation:'replace'}})

Lifecycle


  • onConditionsChange

    Fires new and old condition values.

    onConditionsChange((cond,preCond)=>{console.log(cond)console.log(preCond)})
  • beforeFetch

    Modify conditions before fetch or stop fetch.

    const{ conditions}=useConditionWatcher({  fetcher,  conditions,  beforeFetch})asyncfunctionbeforeFetch(cond,cancel){if(!cond.token){// stop fetchcancel()// will fire onConditionsChange againconditions.token=awaitfetchToken()}returncond})
  • afterFetch &onFetchSuccess

    afterFetch fire beforeonFetchSuccess
    afterFetch can modify data before update.

    TypeModify data before updateDependent request
    afterFetchconfig⭕️⭕️
    onFetchSuccessevent
    <template>     {{ data?.detail }}<!-- 'xxx' --></template>
    const{ data, onFetchSuccess}=useConditionWatcher({ fetcher, conditions,asyncafterFetch(response){//response = { id: 1 }constdetail=awaitfetchDataById(response.id)returndetail// { id: 1, detail: 'xxx' }})})onFetchSuccess((response)=>{console.log(response)// { id: 1, detail: 'xxx' }})
  • onFetchError(config) &onFetchError(event)

    config.onFetchError fire beforeevent.onFetchError
    config.onFetchError can modify data and error before update.

    TypeModify data before updateModify error before update
    onFetchErrorconfig⭕️⭕️
    onFetchErrorevent
    const{ onFetchError}=useConditionWatcher({ fetcher, conditions,onFetchError(ctx){return{data:[],error:'Error message.'}})})onFetchError((error)=>{console.log(error)// origin error data})
  • onFetchFinally

    Will fire on fetch finished.

    onFetchFinally(async()=>{//do something})

Make It Reusable


You might need to reuse the data in many places. It is incredibly easy to create reusable hooks ofvue-condition-watcher :

functionuseUserExpensesHistory(id){const{ conditions, data, error, loading}=useConditionWatcher({fetcher:params=>api.user(id,{ params}),defaultParams:{opt_expand:'amount,place'},conditions:{daterange:[]}immediate:false,initialData:[],beforeFetch(cond,cancel){if(!id){cancel()}const{ daterange, ...baseCond}=condif(daterange.length){[baseCond.created_at_after,baseCond.created_at_before]=[daterange[0],daterange[1]]}returnbaseCond}})return{histories:data,isFetching:loading,isError:error,daterange:conditions.daterange}}

Use in components:

<scriptsetup>  const{daterange,histories,isFetching,isError} = useUserExpensesHistory(route.params.id)  onMounted(() =>{//start first time data fetching after initial date rangedaterange=[newDate(),newDate()]})</script>
<template><el-date-pickerv-model="daterange":disabled="isFetching"type="daterange"/><divv-for="history in histories":key="history.id">    {{ `${history.created_at}: ${history.amount}` }}</div></template>

Congratulations! 🥳 You have learned how to use composition-api withvue-condition-watcher.

Now we can manage the paging information usevue-condition-watcher .

Pagination


Here is an example use Django the limit and offset functions and Element UI.

CreateusePagination hook:

functionusePagination(){letcancelFlag=falseconst{ startLoading, stopLoading}=useLoading()constrouter=useRouter()const{ conditions, data, execute, resetConditions, onConditionsChange, onFetchFinally}=useConditionWatcher({fetcher:api.list,conditions:{daterange:[],limit:20,offset:0},immediate:true,initialData:[],history:{sync:router,ignore:['limit']},    beforeFetch})constcurrentPage=computed({get:()=>conditions.offset/conditions.limit+1,set:(page)=>conditions.offset=(page-1)*conditions.limit})onConditionsChange((newCond,oldCond)=>{if(newCond.offset!==0&&newCond.offset===oldCond.offset){cancelFlag=trueconditions.offset=0}})asyncfunctionbeforeFetch(cond,cancel){if(cancelFlag){cancel()cancelFlag=falsereturncond}awaitnextTick()startLoading()const{ daterange, ...baseCond}=condif(daterange.length){[baseCond.created_at_after,baseCond.created_at_before]=[daterange[0],daterange[1]]}returnbaseCond}onFetchFinally(async()=>{awaitnextTick()stopLoading()window.scrollTo(0,0)})return{    data,    conditions,    currentPage,    resetConditions,refetch:execute}}

Use in components:

<scriptsetup>  const{data,conditions,currentPage,resetConditions,refetch} = usePagination()</script>
<template><el-button@click="refetch">Refetch Data</el-button><el-button@click="resetConditions">Reset Offset</el-button><el-date-pickerv-model="conditions.daterange"type="daterange"/><divv-for="info in data":key="info.id">    {{ info }}</div><el-paginationv-model:currentPage="currentPage"v-model:page-size="conditions.limit":total="data.length"/></template>

Reset offset when daterange or limit changes.

TODO List


  • Error Retry
  • Nuxt SSR SSG Support

Thanks


Inspired byvercel/swr

📄 License


MIT License © 2020-PRESENTRunkids

About

🕶 Data fetching with Vue Composition API. Power of conditions to easily control and sync to the URL query string.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors3

  •  
  •  
  •  

[8]ページ先頭

©2009-2025 Movatter.jp