mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-29 09:02:03 +00:00
feat(nuxt): sync useCookie
state between tabs (#20970)
This commit is contained in:
parent
7695aca93d
commit
a31899af65
@ -18,10 +18,6 @@ const cookie = useCookie(name, options)
|
|||||||
`useCookie` ref will automatically serialize and deserialize cookie value to JSON.
|
`useCookie` ref will automatically serialize and deserialize cookie value to JSON.
|
||||||
::
|
::
|
||||||
|
|
||||||
::alert{icon=⚠️}
|
|
||||||
Multiple invocations of `useCookie` with the same name are not synced. [You can utilise `useState()` to sync them as a workaround](https://github.com/nuxt/nuxt/issues/13020#issuecomment-1505548242).
|
|
||||||
::
|
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
The example below creates a cookie called `counter`. If the cookie doesn't exist, it is initially set to a random value. Whenever we update the `counter` variable, the cookie will be updated accordingly.
|
The example below creates a cookie called `counter`. If the cookie doesn't exist, it is initially set to a random value. Whenever we update the `counter` variable, the cookie will be updated accordingly.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import type { Ref } from 'vue'
|
import type { Ref } from 'vue'
|
||||||
import { ref, watch } from 'vue'
|
import { getCurrentInstance, nextTick, onUnmounted, ref, watch } from 'vue'
|
||||||
import type { CookieParseOptions, CookieSerializeOptions } from 'cookie-es'
|
import type { CookieParseOptions, CookieSerializeOptions } from 'cookie-es'
|
||||||
import { parse, serialize } from 'cookie-es'
|
import { parse, serialize } from 'cookie-es'
|
||||||
import { deleteCookie, getCookie, setCookie } from 'h3'
|
import { deleteCookie, getCookie, setCookie } from 'h3'
|
||||||
@ -34,9 +34,30 @@ export function useCookie<T = string | null | undefined> (name: string, _opts?:
|
|||||||
const cookie = ref<T | undefined>(cookies[name] as any ?? opts.default?.())
|
const cookie = ref<T | undefined>(cookies[name] as any ?? opts.default?.())
|
||||||
|
|
||||||
if (process.client) {
|
if (process.client) {
|
||||||
const callback = () => { writeClientCookie(name, cookie.value, opts as CookieSerializeOptions) }
|
const channel = typeof BroadcastChannel === 'undefined' ? null : new BroadcastChannel(`nuxt:cookies:${name}`)
|
||||||
|
if (getCurrentInstance()) { onUnmounted(() => { channel?.close() }) }
|
||||||
|
|
||||||
|
const callback = () => {
|
||||||
|
writeClientCookie(name, cookie.value, opts as CookieSerializeOptions)
|
||||||
|
channel?.postMessage(cookie.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
let watchPaused = false
|
||||||
|
|
||||||
|
if (channel) {
|
||||||
|
channel.onmessage = (event) => {
|
||||||
|
watchPaused = true
|
||||||
|
cookie.value = event.data
|
||||||
|
nextTick(() => { watchPaused = false })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (opts.watch) {
|
if (opts.watch) {
|
||||||
watch(cookie, callback, { deep: opts.watch !== 'shallow' })
|
watch(cookie, (newVal, oldVal) => {
|
||||||
|
if (watchPaused || isEqual(newVal, oldVal)) { return }
|
||||||
|
callback()
|
||||||
|
},
|
||||||
|
{ deep: opts.watch !== 'shallow' })
|
||||||
} else {
|
} else {
|
||||||
callback()
|
callback()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user