| 134 | * @see https://vueuse.org/useStorage |
| 135 | */ |
| 136 | export function useStorage<T extends (string | number | boolean | object | null)>( |
| 137 | key: MaybeRefOrGetter<string>, |
| 138 | defaults: MaybeRefOrGetter<T>, |
| 139 | storage: StorageLike | undefined, |
| 140 | options: UseStorageOptions<T> = {}, |
| 141 | ): RemovableRef<T> { |
| 142 | const { |
| 143 | flush = 'pre', |
| 144 | deep = true, |
| 145 | listenToStorageChanges = true, |
| 146 | writeDefaults = true, |
| 147 | mergeDefaults = false, |
| 148 | shallow, |
| 149 | window = defaultWindow, |
| 150 | eventFilter, |
| 151 | onError = (e) => { |
| 152 | console.error(e) |
| 153 | }, |
| 154 | initOnMounted, |
| 155 | } = options |
| 156 | |
| 157 | const data = (shallow ? shallowRef : deepRef)(typeof defaults === 'function' ? defaults() : defaults) as RemovableRef<T> |
| 158 | const keyComputed = computed<string>(() => toValue(key)) |
| 159 | |
| 160 | if (!storage) { |
| 161 | try { |
| 162 | storage = getSSRHandler('getDefaultStorage', () => defaultWindow?.localStorage)() |
| 163 | } |
| 164 | catch (e) { |
| 165 | onError(e) |
| 166 | } |
| 167 | } |
| 168 | |
| 169 | if (!storage) |
| 170 | return data |
| 171 | |
| 172 | const rawInit: T = toValue(defaults) |
| 173 | const type = guessSerializerType<T>(rawInit) |
| 174 | const serializer = options.serializer ?? StorageSerializers[type] |
| 175 | |
| 176 | const { pause: pauseWatch, resume: resumeWatch } = watchPausable( |
| 177 | data, |
| 178 | newValue => write(newValue), |
| 179 | { flush, deep, eventFilter }, |
| 180 | ) |
| 181 | |
| 182 | watch(keyComputed, () => update(), { flush }) |
| 183 | |
| 184 | let firstMounted = false |
| 185 | const onStorageEvent = (ev: StorageEvent): void => { |
| 186 | if (initOnMounted && !firstMounted) { |
| 187 | return |
| 188 | } |
| 189 | |
| 190 | update(ev) |
| 191 | } |
| 192 | const onStorageCustomEvent = (ev: CustomEvent<StorageEventLike>): void => { |
| 193 | if (initOnMounted && !firstMounted) { |