========== REWORK BELOW
I used the code from Nuxt.js Smooth Scrolling with Hash Links and added highlighting by adding/removing a class.
// in nuxt.config.js
router: {
scrollBehavior: async (to, from, savedPosition) => {
if (savedPosition) {
return savedPosition
}
const findEl = async (hash, x) => {
return (
document.querySelector(hash) ||
new Promise((resolve, reject) => {
if (x > 50) {
return resolve()
}
setTimeout(() => {
resolve(findEl(hash, ++x || 1))
}, 100)
})
)
}
if (to.hash) {
// scroll to hash in url
const el = await findEl(to.hash)
if ('scrollBehavior' in document.documentElement.style) {
// remove any existing highlight and add highlight
const highlightClass = 'highlight-hash'
const hasClass = document.getElementsByClassName(highlightClass)
Array.from(hasClass).forEach((el) =>
el.classList.remove(highlightClass)
)
el.classList.add(highlightClass)
return window.scrollTo({ top: el.offsetTop, behavior: 'smooth' })
} else {
return window.scrollTo(0, el.offsetTop)
}
}
return { x: 0, y: 0 }
}
}
<ArticleContentSelector
:article="article"
@change="$router.push(...arguments)"
/>
========== REWORK BELOW
The Content selector uses the Vuetify v-select component. When the selector is changed, we push only the hash. The router code above handles scrolling and highlighting.
<v-select
v-model="contentSelected"
class="content-selector"
:items="contentItems"
label="Contents"
outlined
@change="$router.push({ hash: contentSelected })"
></v-select>
Inside of the mounted() method
// on page load, set the Contents selector to the correct element
const noHashHash = this.$route.hash.replace('#', '')
if (noHashHash) {
const id = this.contentItems.findIndex(
(item) => item.value === noHashHash
)
if (id > -1) {
this.selectedItem = id
this.contentSelected = this.contentItems[id].value
}
}