1
- import { reactive , toRefs , ref , watch , Ref , watchEffect , inject , InjectionKey } from 'vue-demi'
2
- import { ConditionsType } from './types'
1
+ import { reactive , ref , watch , watchEffect , inject , onMounted , onUnmounted } from 'vue-demi'
2
+ import { ConditionsType , Config , QueryOptions , ResultInterface } from './types'
3
3
import { filterNoneValueObject , createParams , stringifyQuery , syncQuery2Conditions } from './utils'
4
+ import { useFetchData } from './useFetchData'
5
+ import { useParseQuery } from './useParseQuery'
4
6
import clone from 'rfdc'
5
- import { Router } from 'vue-router'
6
-
7
- type FetcherType = ( params : ConditionsType ) => Promise < any >
8
- type ProvideKeyName < T > = InjectionKey < T > | string
9
-
10
- interface QueryOptions < T > {
11
- sync ?: ProvideKeyName < T >
12
- ignore ?: string [ ]
13
- }
14
-
15
- interface Config {
16
- fetcher : FetcherType
17
- conditions : ConditionsType
18
- defaultParams ?: ConditionsType
19
- beforeFetch ?: ( conditions : ConditionsType ) => ConditionsType
20
- }
21
-
22
- interface ResultInterface {
23
- conditions : { [ x : string ] : any }
24
- loading : Ref < boolean | false >
25
- data : Ref < any | null >
26
- refresh : Ref < ( ) => void >
27
- error : Ref < any | null >
28
- }
29
7
30
8
export default function useConditionWatcher < T extends Config , E extends QueryOptions < E > > (
31
9
config : T ,
32
10
queryOptions ?: E
33
11
) : ResultInterface {
34
- let router : Router
12
+ let router = null
35
13
const _conditions = reactive ( config . conditions )
36
14
const loading = ref ( false )
37
15
const data = ref ( null )
@@ -40,6 +18,13 @@ export default function useConditionWatcher<T extends Config, E extends QueryOpt
40
18
const query = ref ( { } )
41
19
const completeInitialConditions = ref ( false )
42
20
21
+ const syncConditionsByQuery = ( ) => {
22
+ const { query : initQuery } = useParseQuery ( )
23
+ console . log ( 'initQuery== ' , initQuery )
24
+ syncQuery2Conditions ( _conditions , initQuery )
25
+ completeInitialConditions . value = true
26
+ }
27
+
43
28
const fetch = ( conditions : ConditionsType ) : void => {
44
29
const { loading : fetchLoading , result : fetchResult , error : fetchError , use : fetchData } = useFetchData ( ( ) =>
45
30
config . fetcher ( conditions )
@@ -90,42 +75,30 @@ export default function useConditionWatcher<T extends Config, E extends QueryOpt
90
75
}
91
76
)
92
77
93
- if (
94
- queryOptions &&
95
- ( typeof queryOptions . sync === 'string' || typeof queryOptions . sync === 'function' ) &&
96
- queryOptions . sync . length
97
- ) {
78
+ if ( queryOptions && typeof queryOptions . sync === 'string' && queryOptions . sync . length ) {
98
79
router = inject ( queryOptions . sync )
99
- if ( router && router . isReady ) {
100
- router . isReady ( ) . then ( ( ) => {
101
- // watch query changed
102
- watch ( query , async ( ) => {
103
- const path : string = router . currentRoute . value . path
104
- const queryString = stringifyQuery ( query . value , queryOptions . ignore || [ ] )
105
- completeInitialConditions . value = false
106
- await router . push ( path + '?' + queryString )
107
- } )
80
+ if ( router ) {
81
+ // initial conditions by window.location.search. just do once.
82
+ syncConditionsByQuery ( )
83
+ // watch query changed
84
+ watch ( query , async ( ) => {
85
+ const path : string = router . currentRoute . value . path
86
+ const queryString = stringifyQuery ( query . value , queryOptions . ignore || [ ] )
87
+ await router . push ( path + '?' + queryString )
88
+ } )
89
+
90
+ onMounted ( ( ) => {
91
+ window . addEventListener ( 'popstate' , syncConditionsByQuery )
92
+ } )
93
+ onUnmounted ( ( ) => {
94
+ window . removeEventListener ( 'popstate' , syncConditionsByQuery )
108
95
} )
109
- // watch router changed
110
- watch (
111
- router . currentRoute ,
112
- ( currentRoute , preCurrentRoute ) => {
113
- const oldFullPath = preCurrentRoute ? preCurrentRoute . fullPath : ''
114
- if ( currentRoute . fullPath !== oldFullPath ) {
115
- //back/forward page sync query string to _conditions
116
- syncQuery2Conditions ( _conditions , currentRoute . query )
117
- completeInitialConditions . value = true
118
- }
119
- } ,
120
- {
121
- immediate : true ,
122
- }
123
- )
124
96
} else {
125
- throw new ReferenceError ( '[vue-condition-watcher] Could not found vue-router instance.' )
97
+ throw new ReferenceError (
98
+ `[vue-condition-watcher] Could not found vue-router instance. Please check key: ${ queryOptions . sync } is right!`
99
+ )
126
100
}
127
101
}
128
-
129
102
completeInitialConditions . value = true
130
103
131
104
return {
@@ -136,33 +109,3 @@ export default function useConditionWatcher<T extends Config, E extends QueryOpt
136
109
error,
137
110
}
138
111
}
139
-
140
- function useFetchData < T > ( fetcher : ( ) => Promise < T > ) {
141
- const state = reactive ( {
142
- loading : false ,
143
- error : null ,
144
- result : null ,
145
- } )
146
-
147
- let lastPromise : Promise < T >
148
- const use = async ( ) => {
149
- state . error = null
150
- state . loading = true
151
- const promise = ( lastPromise = fetcher ( ) )
152
- try {
153
- const result = await promise
154
- if ( lastPromise === promise ) {
155
- state . result = result
156
- }
157
- } catch ( e ) {
158
- state . error = e
159
- } finally {
160
- state . loading = false
161
- }
162
- }
163
-
164
- return {
165
- ...toRefs ( state ) ,
166
- use,
167
- }
168
- }
0 commit comments