-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
zuofenghua
committed
Jul 28, 2021
1 parent
1092ac7
commit a64371b
Showing
10 changed files
with
358 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,19 @@ | ||
export * from './useToggle'; | ||
export * from './useFullscreen'; | ||
export * from './useLocalStorageState'; | ||
export * from './useAxios'; | ||
export * from './useDebounce'; | ||
export * from './useDocumentVisibility'; | ||
export * from './useFullscreen'; | ||
export * from './useHover'; | ||
export * from './useInViewport'; | ||
export * from './useSize'; | ||
export * from './useWorkerFunction'; | ||
export * from './useThrottle'; | ||
export * from './useDebounce'; | ||
export * from './useTable'; | ||
export * from './useKeyPress'; | ||
export * from './useLocalforage'; | ||
export * from './useLocalStorageState'; | ||
export * from './useOLAP'; | ||
export * from './useRequest'; | ||
export * from './usePaginatedRequest'; | ||
export * from './useAxios'; | ||
export * from './useLocalforage'; | ||
export * from './useRequest'; | ||
export * from './useSize'; | ||
export * from './useTable'; | ||
export * from './useThrottle'; | ||
export * from './useToggle'; | ||
export * from './useUrlState'; | ||
export * from './useWorkerFunction'; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<template> | ||
<div> | ||
<p>{{ state }}</p> | ||
<button @click="addCount()">count++</button> | ||
<button @click="subCount()">count--</button> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts" setup> | ||
import { useUrlState } from 'ahooks-vue'; | ||
const routerPushFn = (s: string) => (location.hash = s); | ||
const DefaultState = { count: 0, page: 1 }; | ||
const state = useUrlState(routerPushFn, DefaultState, { | ||
localStorageKey: 'localStorageKey', | ||
}); | ||
const addCount = () => state.value.count++; | ||
const subCount = () => state.value.count--; | ||
</script> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './demo.vue'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
--- | ||
map: | ||
path: /use-url-state | ||
--- | ||
|
||
# useUrlState | ||
|
||
一个同步组件内部状态和 query 参数的 hook。 | ||
|
||
::: warning | ||
API 有改动,见[ahooks](https://ahooks.js.org/zh-CN/hooks/state)。 | ||
::: | ||
|
||
## Examples | ||
|
||
### Basic usage | ||
|
||
<demo src="./demo/demo.vue" | ||
language="vue" | ||
title="Basic usage" | ||
desc="同步条件到url,在需要通过url分享复杂参数场景十分有用"> | ||
</demo> | ||
|
||
## API | ||
|
||
```typescript | ||
const state = useUrlState(routerPush, DefaultState, { | ||
localStorageKey: 'localStorageKey', | ||
}); | ||
|
||
interface UseUrlStateOptions { | ||
localStorageKey?: string; | ||
} | ||
``` | ||
|
||
### Params | ||
|
||
| Property | Description | Type | Default | | ||
| ------------ | --------------------------------------------------------------------------------------------------------------------- | --------------- | ------- | | ||
| routerPushFn | Pass `router.push` | `function` | - | | ||
| initialState | defaultValue | `S | (() => S)` | - | | ||
| options | If set the `options.localStorageKey` is set, state will use the state saved in localStorage when url params is empty. | UseUrlStateOptions | - | | ||
|
||
### Result | ||
|
||
| Property | Description | Type | | ||
| -------- | ----------- | ---- | | ||
| state | state ref | - | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
import qs from 'qs'; | ||
import { Ref, ref, watch } from 'vue-demi'; | ||
import { useLocalStorageState } from '../useLocalStorageState'; | ||
|
||
export interface UseUrlStateOptions { | ||
localStorageKey?: string; | ||
} | ||
|
||
interface UrlState { | ||
[key: string]: any; | ||
} | ||
|
||
function encodeParams(value: UrlState) { | ||
return qs.stringify(value); | ||
} | ||
|
||
function decodeParams(valueStr: string) { | ||
// return JSON.parse(decodeURIComponent(atob(valueStr))); | ||
return qs.parse(valueStr, { | ||
decoder(str, decoder, charset) { | ||
const strWithoutPlus = str.replace(/\+/g, ' '); | ||
if (charset === 'iso-8859-1') { | ||
// unescape never throws, no try...catch needed: | ||
return strWithoutPlus.replace(/%[0-9a-f]{2}/gi, unescape); | ||
} | ||
|
||
if (/^[+-]?\d+(\.\d+)?$/.test(str)) { | ||
return parseFloat(str); | ||
} | ||
|
||
const keywords: Record<string, any> = { | ||
true: true, | ||
false: false, | ||
null: null, | ||
undefined, | ||
}; | ||
if (str in keywords) { | ||
return keywords[str]; | ||
} | ||
|
||
// utf-8 | ||
try { | ||
return decodeURIComponent(strWithoutPlus); | ||
} catch (e) { | ||
return strWithoutPlus; | ||
} | ||
}, | ||
}); | ||
} | ||
|
||
export function useUrlState<S extends UrlState = UrlState>( | ||
routerPushFn: (path: string) => void, | ||
initialState?: S | (() => S), | ||
options?: UseUrlStateOptions, | ||
): Ref<S> { | ||
const { localStorageKey } = options ?? {}; | ||
|
||
const [path, paramsStr] = location.hash.slice(1).split('?'); | ||
|
||
const defaultState = | ||
(typeof initialState === 'function' | ||
? (initialState as () => S)() | ||
: initialState) ?? ({} as S); | ||
let state = ref(defaultState) as Ref<S>; | ||
|
||
if (localStorageKey) { | ||
state = useLocalStorageState(localStorageKey, defaultState) as Ref<S>; | ||
} | ||
|
||
// 初始状态 url > localstorage | ||
if (paramsStr) { | ||
try { | ||
const paramsValue = decodeParams(paramsStr); | ||
console.log('解析url结果:'); | ||
console.log(paramsValue); | ||
state.value = { | ||
...defaultState, | ||
...state.value, | ||
...paramsValue, | ||
}; | ||
} catch { | ||
state.value = defaultState; | ||
} | ||
} | ||
|
||
// 去掉多余的key | ||
if (initialState && Object.keys(initialState).length) { | ||
let newState = { ...initialState } as any; | ||
for (const key in newState) { | ||
if (key in state.value) { | ||
newState[key] = state.value[key]; | ||
} | ||
} | ||
state.value = newState; | ||
} | ||
|
||
// 把params写到url | ||
watch( | ||
state, | ||
() => { | ||
const newParamsStr = encodeParams(state.value); | ||
|
||
routerPushFn(`${path}?${newParamsStr}`); | ||
console.log('写url'); | ||
console.log(`${path}?${newParamsStr}`); | ||
}, | ||
{ | ||
deep: true, | ||
immediate: true, | ||
}, | ||
); | ||
|
||
return state; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
--- | ||
map: | ||
path: /use-url-state | ||
--- | ||
|
||
# useUrlState | ||
|
||
一个同步组件内部状态和 query 参数的 hook。 | ||
|
||
::: warning | ||
API 有改动,见[ahooks](https://ahooks.js.org/zh-CN/hooks/state)。 | ||
::: | ||
|
||
## Examples | ||
|
||
### 基础用法 | ||
|
||
<demo src="./demo/demo.vue" | ||
language="vue" | ||
title="基础用法" | ||
desc="同步条件到url,在需要通过url分享复杂参数场景十分有用"> | ||
</demo> | ||
|
||
## API | ||
|
||
```typescript | ||
const state = useUrlState(routerPush, DefaultState, { | ||
localStorageKey: 'localStorageKey', | ||
}); | ||
|
||
interface UseUrlStateOptions { | ||
localStorageKey?: string; | ||
} | ||
``` | ||
|
||
### Params | ||
|
||
| 参数 | 说明 | 类型 | 默认值 | | ||
| ------------ | ------------------------------------------------------------------------ | ------------------ | ------ | | ||
| routerPushFn | 一般来说,传 vue-router 的 `router.push`方法就行 | `function` | - | | ||
| initialState | 默认值 | `S | (() => S)` | - | | ||
| options | 设置`localStorageKey`的话,若 url 没有参数,会使用存在 localStorage 的值 | UseUrlStateOptions | - | | ||
|
||
### Result | ||
|
||
| 参数 | 说明 | 类型 | | ||
| ----- | ------ | ---- | | ||
| state | 状态值 | - | |
Oops, something went wrong.