admin管理员组文章数量:1279017
I'm getting started with Svelte and building a single-page application (using page.js as the router). I thought I'd have a separate ponent to produce the <svelte:head>
block, and when each ponent mounts it would write the page title to a store, which would then be read by the head ponent. It partially works - the page title is updated when I click through to different pages. However, if I go back in my browser's history, the title doesn't change back with the page. It does change if I then reload the page. So perhaps onMount()
isn't the right lifecycle method. What approach can I take that will work with history state navigation?
Here's my app boiled down to a minimal example.
// 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>
I'm getting started with Svelte and building a single-page application (using page.js as the router). I thought I'd have a separate ponent to produce the <svelte:head>
block, and when each ponent mounts it would write the page title to a store, which would then be read by the head ponent. It partially works - the page title is updated when I click through to different pages. However, if I go back in my browser's history, the title doesn't change back with the page. It does change if I then reload the page. So perhaps onMount()
isn't the right lifecycle method. What approach can I take that will work with history state navigation?
Here's my app boiled down to a minimal example.
// 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>
Share
Improve this question
edited Sep 5, 2020 at 16:50
Hex
asked Nov 23, 2019 at 23:41
HexHex
1,3662 gold badges17 silver badges28 bronze badges
1 Answer
Reset to default 13For some reasons, Svelte doesn't seem to like the <title>
in an {#if}
block... I remend puting the value in a reactive statement instead.
$: title = $pageName ? `Test App \u2014 ${$pageName}` : 'Test App'
$pageName
is a special syntax to access the store's value without having to handle subscribe/unsubscribe yourself (docs).
Even with that, I found that my browser (tested in Chrome) was apparently OK with ignoring the <title>
in the DOM when navigating back. We can force the value of document.title
to workaround that. Another reactive block can take care of that:
$: {
document.title = title
}
So your whole Head.svelte
ponent would now looks like this:
<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>
And finally, in your example, you're not updating the store's value when you navigate to /
, so you'd have a stale title in this case. I think you need to add a route like so:
page('/', () => app.$set({ route: null }))
本文标签: javascriptBest placelifecycle method to set page titles in a singlepage Svelte appStack Overflow
版权声明:本文标题:javascript - Best placelifecycle method to set page titles in a single-page Svelte app - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741224003a2361515.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论