javascript - 在单页 Svelte 应用程序中设置页面标题的最佳位置/生命周期方法
问题描述
我开始使用 Svelte 并构建单页应用程序(使用page.js作为路由器)。我以为我有一个单独的组件来生成<svelte:head>
块,当每个组件安装时,它会将页面标题写入存储,然后由头组件读取。它部分有效 - 当我点击不同的页面时,页面标题会更新。但是,如果我返回浏览器的历史记录,标题不会随页面变回。如果我重新加载页面,它确实会改变。所以也许onMount()
不是正确的生命周期方法。我可以采取什么方法与历史状态导航一起使用?
这是我的应用程序归结为一个最小的例子。
// index.js
import page from 'page'
import App from './views/App.svelte'
const app = new App({
target: document.body,
props: {
route: null,
},
})
function one() {
app.$set({ route: 'one' })
}
function two() {
app.$set({ route: 'two' })
}
page('/one', one)
page('/two', two)
page()
// App.svelte
<script>
import One from './One.svelte'
import Two from './Two.svelte'
import Head from '../parts/Head.svelte'
import Home from './Home.svelte'
export let route
</script>
<Head />
{#if route === 'one'}
<One />
{:else if route === 'two'}
<Two />
{:else}
<Home />
{/if}
// Head.svelte
<script>
import { pageName } from '../stores.js'
let displayPageName
pageName.subscribe(value => {
displayPageName = value
})
</script>
<svelte:head>
{#if displayPageName}
<title>Test App — {displayPageName}</title>
{:else}
<title>Test App</title>
{/if}
</svelte:head>
// stores.js
import { writable } from 'svelte/store'
export const pageName = writable(null)
// Home.svelte
<a href="/one">One</a> <a href="/two">Two</a>
// One.svelte
<script>
import { onMount } from 'svelte'
import { pageName } from '../stores.js'
onMount(async () => {
pageName.update(() => 'Component One')
})
</script>
<a href="/two">Two</a>
// Two.svelte
<script>
import { onMount } from 'svelte'
import { pageName } from '../stores.js'
onMount(async () => {
pageName.update(() => 'Component Two')
})
</script>
<a href="/one">One</a>
解决方案
由于某些原因,Svelte 似乎不喜欢<title>
in a {#if}
block... 我建议改为在响应式语句中计算值。
$: title = $pageName ? `Test App \u2014 ${$pageName}` : 'Test App'
$pageName
是一种无需自己处理订阅/取消订阅(docs)即可访问商店值的特殊语法。
即便如此,我发现我的浏览器(在 Chrome 中测试)显然可以<title>
在返回时忽略 DOM 中的 。我们可以强制使用 的值document.title
来解决这个问题。另一个反应块可以解决这个问题:
$: {
document.title = title
}
所以你的整个Head.svelte
组件现在看起来像这样:
<script>
import { pageName } from '../stores.js'
$: title = $pageName ? `Test App \u2014 ${$pageName}` : 'Test App'
$: {
document.title = title
}
</script>
<svelte:head>
<title>{title}</title>
</svelte:head>
最后,在您的示例中,当您导航到 时,您不会更新商店的值/
,因此在这种情况下您将拥有一个过时的标题。我认为您需要添加这样的路线:
page('/', () => app.$set({ route: null }))
推荐阅读
- android - 如何使用处理程序运行重复任务
- python - Bazel 0.26.1 在 py_test 上使用 Python3
- lua - 有没有办法让用 Luarocks 安装的 Lua 脚本在运行时找到它的安装前缀?
- hadoop - 提前知道 Hive 行将去哪个桶
- java - Spring手动创建组件并注册为单例
- python - 根据另一个系列的条件,使用字典替换系列对象中的项目
- laravel - Laravel - 如何从数据库中检索最后保存的数据并显示它
- r - 将 R 统计信息输出为有组织的 LaTeX 表
- here-api - 传递参数以在 HERE 反向地理编码中获取最近的道路名称或建筑物名称
- python - 在 python 中打印一个直角三角形,从输入 n 开始,行 n