在组件生命周期之外从 SvelteKit 的 $app/stores 获取值
Get values from SvelteKit's $app/stores outside of the lifecycle of a component
我的 Svelte 组件像这样导入可读存储:
import { classes, locations, schedule } from 'stores.ts'
在 stores.ts 中,我想构建 URL 以使用来自 $app/stores.
的 page.host 动态获取
// Note: this is not a Svelte component; it's stores.ts
import { readable } from 'svelte/store'
import { getStores } from '$app/stores'
const { page } = getStores()
let FQDN
page.subscribe(({ host }) => {
FQDN = host
})
const getArray = async (url) => {
const response: Response = await fetch(url)
if (!response.ok) throw new Error(`Bad response trying to retrieve from ${url}.`)
return await response.json()
}
const getReadableStore = (url: string) => readable([], set => {
getArray(`http://${FQDN}${url}`)
.then(set)
.catch(err => console.error('Failed API call:', err))
return () => {}
})
export const classes = getReadableStore('/api/class/public.json')
export const locations = getReadableStore('/api/location/public.json')
export const schedule = getReadableStore('/api/schedule/public.json')
第六行抛出这个错误...
Error: Function called outside component initialization
at get_current_component (/Users/nates/dev/shy-svelte/node_modules/svelte/internal/index.js:652:15)
at Proxy.getContext (/Users/nates/dev/shy-svelte/node_modules/svelte/internal/index.js:685:12)
at Module.getStores (/.svelte-kit/dev/runtime/app/stores.js:17:26)
at eval (/src/stores.ts:6:38)
at instantiateModule (/Users/nates/dev/shy-svelte/node_modules/@sveltejs/kit/node_modules/vite/dist/node/chunks/dep-e9a16784.js:68197:166)
两个问题...
- 在组件上下文之外从 $app/stores 获取页面值的正确方法是什么?这可能吗? 下面的回答:不,这在组件上下文之外是不可能的。
- 如果我正在访问 SvelteKit 站点,假设
http://localhost:3000/something
或 https://example.com
并且 Svelte 组件从 stores.ts 加载可读存储,[=45 中有没有办法=] 来确定加载组件(从 stores.ts 加载)的原始页面请求是 http 还是 https? 下面的回答:不,这在 stores.ts 中是不可能的 - 只能从一个组件。
更新: 根据反馈,我将在我的 .env 中设置一个名为 VITE_WEB_URL=http://localhost:3000 的值并更改它用于生产系统。这减少了代码行数,可能是一种更好的做法(欢迎评论)...
// revised stores.ts
import { readable } from 'svelte/store'
const { VITE_WEB_URL } = import.meta.env
const getArray = async (url) => {
const response: Response = await fetch(url)
if (!response.ok) throw new Error(`Bad response trying to retrieve from ${url}.`)
return await response.json()
}
const getReadableStore = (url: string) => readable([], set => {
getArray(`${VITE_WEB_URL}${url}`)
.then(set)
.catch(err => console.error('Failed API call:', err))
return () => {}
})
export const classes = getReadableStore('/api/class/public.json')
export const locations = getReadableStore('/api/location/public.json')
export const schedule = getReadableStore('/api/schedule/public.json')
引用 svelte store 随处可见。
但是,使用 $: shorthand 语法仅适用于组件。
$: BASE = `http://${$page.host}`
- SvelteKit 似乎委托这个来获取确实
Because of that, the stores are not free-floating objects: they must be accessed during component initialisation, like anything else that would be accessed with getContext.
- 因此,由于可读存储绑定到 svelte 组件的上下文,我建议您在 SvelteKit 网站的组件内订阅任何一种方式($ 或 .subscribe),然后发送协议值(http 或 https ) 作为更新时的参数,以便 stores.ts 将其存储在变量中。
不过好像SvelteKit没有提供protocol值,所以在page subscription中解析client端window.location.href然后发送
我的 Svelte 组件像这样导入可读存储:
import { classes, locations, schedule } from 'stores.ts'
在 stores.ts 中,我想构建 URL 以使用来自 $app/stores.
的 page.host 动态获取// Note: this is not a Svelte component; it's stores.ts
import { readable } from 'svelte/store'
import { getStores } from '$app/stores'
const { page } = getStores()
let FQDN
page.subscribe(({ host }) => {
FQDN = host
})
const getArray = async (url) => {
const response: Response = await fetch(url)
if (!response.ok) throw new Error(`Bad response trying to retrieve from ${url}.`)
return await response.json()
}
const getReadableStore = (url: string) => readable([], set => {
getArray(`http://${FQDN}${url}`)
.then(set)
.catch(err => console.error('Failed API call:', err))
return () => {}
})
export const classes = getReadableStore('/api/class/public.json')
export const locations = getReadableStore('/api/location/public.json')
export const schedule = getReadableStore('/api/schedule/public.json')
第六行抛出这个错误...
Error: Function called outside component initialization at get_current_component (/Users/nates/dev/shy-svelte/node_modules/svelte/internal/index.js:652:15) at Proxy.getContext (/Users/nates/dev/shy-svelte/node_modules/svelte/internal/index.js:685:12) at Module.getStores (/.svelte-kit/dev/runtime/app/stores.js:17:26) at eval (/src/stores.ts:6:38) at instantiateModule (/Users/nates/dev/shy-svelte/node_modules/@sveltejs/kit/node_modules/vite/dist/node/chunks/dep-e9a16784.js:68197:166)
两个问题...
- 在组件上下文之外从 $app/stores 获取页面值的正确方法是什么?这可能吗? 下面的回答:不,这在组件上下文之外是不可能的。
- 如果我正在访问 SvelteKit 站点,假设
http://localhost:3000/something
或https://example.com
并且 Svelte 组件从 stores.ts 加载可读存储,[=45 中有没有办法=] 来确定加载组件(从 stores.ts 加载)的原始页面请求是 http 还是 https? 下面的回答:不,这在 stores.ts 中是不可能的 - 只能从一个组件。
更新: 根据反馈,我将在我的 .env 中设置一个名为 VITE_WEB_URL=http://localhost:3000 的值并更改它用于生产系统。这减少了代码行数,可能是一种更好的做法(欢迎评论)...
// revised stores.ts
import { readable } from 'svelte/store'
const { VITE_WEB_URL } = import.meta.env
const getArray = async (url) => {
const response: Response = await fetch(url)
if (!response.ok) throw new Error(`Bad response trying to retrieve from ${url}.`)
return await response.json()
}
const getReadableStore = (url: string) => readable([], set => {
getArray(`${VITE_WEB_URL}${url}`)
.then(set)
.catch(err => console.error('Failed API call:', err))
return () => {}
})
export const classes = getReadableStore('/api/class/public.json')
export const locations = getReadableStore('/api/location/public.json')
export const schedule = getReadableStore('/api/schedule/public.json')
引用 svelte store 随处可见。 但是,使用 $: shorthand 语法仅适用于组件。
$: BASE = `http://${$page.host}`
- SvelteKit 似乎委托这个来获取确实
Because of that, the stores are not free-floating objects: they must be accessed during component initialisation, like anything else that would be accessed with getContext.
- 因此,由于可读存储绑定到 svelte 组件的上下文,我建议您在 SvelteKit 网站的组件内订阅任何一种方式($ 或 .subscribe),然后发送协议值(http 或 https ) 作为更新时的参数,以便 stores.ts 将其存储在变量中。
不过好像SvelteKit没有提供protocol值,所以在page subscription中解析client端window.location.href然后发送