Skip to content

Commit

Permalink
fix: prevent parent components from overriding tags in child components
Browse files Browse the repository at this point in the history
normally tags in child components take higher priority than that in parent components, but before this change when `title`  in a parent component is changed, it will override the `title` in child components, which is unexpected.
  • Loading branch information
egoist committed Mar 4, 2021
1 parent 225ae1c commit 9a14c62
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 41 deletions.
29 changes: 24 additions & 5 deletions example/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,30 @@ import {
} from 'vue-router'
import { createHead, useHead } from '../src'

const Home = defineComponent({
const Counter = defineComponent({
setup() {
const count = ref(0)
useHead({
title: computed(() => `count: ${count.value}`),
})
return () => (
<button
class="counter"
onClick={() => {
count.value++
}}
>
{count.value}
</button>
)
},
})

const Home = defineComponent({
setup() {
const title = ref('Home')
useHead({
title,
base: { href: '/' },
style: [{ children: `body {background: red}` }],
htmlAttrs: {
Expand Down Expand Up @@ -44,12 +63,12 @@ const Home = defineComponent({
<RouterLink to="/about">About</RouterLink>
<hr />
<button
onClick={() => {
count.value++
}}
class="change-home-title"
onClick={() => (title.value = 'new title')}
>
{count.value}
Change home title (not really)
</button>
<Counter />
</div>
)
},
Expand Down
94 changes: 59 additions & 35 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export type Head = {

removeHeadTags: (tags: HeadTag[]) => void

updateHeadTags: (oldTags: HeadTag[], newTags: HeadTag[]) => void

updateDOM: (document?: Document) => void
}

Expand Down Expand Up @@ -211,55 +213,72 @@ const insertTags = (tags: HeadTag[], document = window.document) => {
}

export const createHead = () => {
const headTags: HeadTag[] = []
let allHeadTags: HeadTag[][] = []

const head: Head = {
install(app) {
app.config.globalProperties.$head = head
app.provide(PROVIDE_KEY, head)
},

headTags,

addHeadTags(tags) {
tags.forEach((tag) => {
if (tag.tag === 'meta' || tag.tag === 'base') {
// Remove tags with the same key
const key = getTagKey(tag.props)
if (key) {
let index = -1

for (let i = 0; i < headTags.length; i++) {
const prev = headTags[i]
const prevValue = prev.props[key.name]
const nextValue = tag.props[key.name]
if (prev.tag === tag.tag && prevValue === nextValue) {
index = i
break
/**
* Get deduped tags
*/
get headTags() {
const deduped: HeadTag[] = []

allHeadTags.forEach((tags) => {
tags.forEach((tag) => {
if (tag.tag === 'meta' || tag.tag === 'base') {
// Remove tags with the same key
const key = getTagKey(tag.props)
if (key) {
let index = -1

for (let i = 0; i < deduped.length; i++) {
const prev = deduped[i]
const prevValue = prev.props[key.name]
const nextValue = tag.props[key.name]
if (prev.tag === tag.tag && prevValue === nextValue) {
index = i
break
}
}
}

if (index !== -1) {
headTags.splice(index, 1)
if (index !== -1) {
deduped.splice(index, 1)
}
}
}
}

headTags.push(tag)
deduped.push(tag)
})
})

return deduped
},

removeHeadTags(tags) {
tags.forEach((tag) => {
const index = headTags.indexOf(tag)
if (index !== -1) {
headTags.splice(index, 1)
addHeadTags(tags) {
allHeadTags.push(tags)
},

updateHeadTags(oldTags, newTags) {
allHeadTags = allHeadTags.map((v) => {
if (v === oldTags) {
return newTags
}
return v
})
},

removeHeadTags(tags) {
allHeadTags = allHeadTags.filter((v) => {
return tags !== v
})
},

updateDOM(document) {
insertTags(headTags, document)
insertTags(head.headTags, document)
},
}
return head
Expand All @@ -277,19 +296,24 @@ export const useHead = (

if (IS_BROWSER) {
let tags: HeadTag[] | undefined
let oldTags: HeadTag[] | undefined

watchEffect(() => {
if (tags) {
head.removeHeadTags(tags)
}
tags = headObjToTags(headObj.value)
head.addHeadTags(tags)

if (oldTags) {
head.updateHeadTags(oldTags, tags)
} else {
head.addHeadTags(tags)
}

oldTags = tags
head.updateDOM()
})

onBeforeUnmount(() => {
if (tags) {
head.removeHeadTags(tags)
if (oldTags) {
head.removeHeadTags(oldTags)
head.updateDOM()
}
})
Expand Down
5 changes: 4 additions & 1 deletion tests/test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,10 @@ test('browser', async (t) => {
<base href="/"><style>body {background: red}</style><meta name="description" content="desc 2"><meta property="og:locale:alternate" content="fr"><meta property="og:locale:alternate" content="zh"><meta name="head:count" content="5">`,
)

await page.click('button')
await page.click('button.counter')
t.is(await page.title(), 'count: 1')

await page.click('button.change-home-title')
t.is(await page.title(), 'count: 1')

await page.click('a[href="/about"]')
Expand Down

0 comments on commit 9a14c62

Please sign in to comment.