Code Monkey home page Code Monkey logo

head's Introduction

VueUse - Collection of essential Vue Composition Utilities VueUse - Collection of essential Vue Composition Utilities
Collection of essential Vue Composition Utilities

NPM version NPM Downloads Docs & Demos Function Count
GitHub stars

๐Ÿš€ Features

  • ๐ŸŽช Interactive docs & demos
  • ๐Ÿ•ถ Seamless migration: Works for both Vue 3 and 2
  • โšก Fully tree shakeable: Only take what you want, bundle size
  • ๐Ÿฆพ Type Strong: Written in TypeScript, with TS Docs
  • ๐Ÿ”‹ SSR Friendly
  • ๐ŸŒŽ No bundler required: Usable via CDN
  • ๐Ÿ”ฉ Flexible: Configurable event filters and targets
  • ๐Ÿ”Œ Optional Add-ons: Router, Firebase, RxJS, etc.

๐Ÿฆ„ Usage

import { useLocalStorage, useMouse, usePreferredDark } from '@vueuse/core'

export default {
  setup() {
    // tracks mouse position
    const { x, y } = useMouse()

    // if user prefers dark theme
    const isDark = usePreferredDark()

    // persist state in localStorage
    const store = useLocalStorage(
      'my-storage',
      {
        name: 'Apple',
        color: 'red',
      },
    )

    return { x, y, isDark, store }
  },
}

Refer to functions list or documentations for more details.

๐Ÿ“ฆ Install

๐ŸŽฉ From v4.0, it works for Vue 2 & 3 within a single package by the power of vue-demi!

npm i @vueuse/core

Add ons | Nuxt Module

From v6.0, VueUse requires vue >= v3.2 or @vue/composition-api >= v1.1

Demos

CDN

<script src="https://unpkg.com/@vueuse/shared"></script>

<script src="https://unpkg.com/@vueuse/core"></script>

It will be exposed to global as window.VueUse

๐Ÿชด Project Activity

Alt

๐Ÿงฑ Contribute

See the Contributing Guide

๐ŸŒธ Thanks

This project is heavily inspired by the following awesome projects.

And thanks to all the contributors on GitHub!

๐Ÿ‘จโ€๐Ÿš€ Contributors

Financial Contributors on Open Collective

๐Ÿ“„ License

MIT License ยฉ 2019-PRESENT Anthony Fu

head's People

Contributors

anteriovieira avatar antfu avatar bobbiegoede avatar c1rus avatar dargmuesli avatar dpschen avatar egoist avatar fallemand avatar github-actions[bot] avatar harlan-zw avatar huang-julien avatar killmenot avatar mannil avatar raineorshine avatar rphippswiley avatar vis97c avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

head's Issues

Render Context?

The new library looks great. Sorely needed.

From looking at the docs, there is nothing mentioned about providing the context (e.g. the route url) for the rendering.

I know that renderToString supports a second context argument:

const HTML = renderToString(app, {url: '/whatever'})

How does the SSR code address this?

Documentation does not specify where to place the "Server-side rendering"

Hello, first at all thank you for the Document manager. Just more like a suggestion, and a question as well, also for people that never had to work with metas in the past like me, might be not aware where and how to configure the ssr part. It's not specify, I also checked the repository looking for this part. In general will be cool to have a tutorial for this plugin because I noticed there not much information around on the web, and the places that I found where just a copy and paste from the read me file. :)

Problem with link metadata

For some reason, the link head object is duplicating in SSR. In Vue 3 I create my head tags like this:


 HTMLHead.value = {
              title: `${Product.value[0].title`,
              meta: [
                {
                  name: "description",
                  content: `${Product.value[0].description},
                },
                {
                  name: "date",
                  content: `${Product.value[0].datecreated}`
                }
              ],
              link: [
                {
                  rel: "canonical",
                  href: `https://www.example.com/product/${Production.value[0].urlslug}`
                }
              ]
            }

The title and meta tags render fine in SSR, but the link object duplicates each time a page is refreshed. If I navigate to other pages, then those other pages link elements also appear in the current product page which makes no sense. I cannot understand why it is being duplicated and the title and meta objects do not.

Example output I end up with after 3 refreshes of the same page is:

<title>Nintendo Switch</title>
<link rel="canonical" href="https://www.example.com/product/nintendo-switch">
<link rel="canonical" href="https://www.example.com/product/nintendo-switch">
<link rel="canonical" href="https://www.example.com/product/nintendo-switch">
          
<meta name="description"content="The new Nintendo Switch is availabe now">
<meta name="date" content="2021-09-13T11:55:56.195Z">

The link tag always ends up being placed immediately after the title tag and it repeats over and over again (once per page refresh). If I then visit a different product page I end up with this output:

<title>Nintendo Switch</title>
<link rel="canonical" href="https://www.example.com/product/nintendo-switch">
<link rel="canonical" href="https://www.example.com/product/nintendo-switch">
<link rel="canonical" href="https://www.example.com/product/nintendo-switch">
<link rel="canonical" href="https://www.example.com/product/sony-ps4-playstation-4-pro">

<meta name="description" content="The best version of the Sony PS4 is the Pro edition">
<meta name="date" content="2021-09-11T09:21:44.160Z">

So as you can see the old page link tags still exist and then the new product page link tag is appended to the end. If a user visits many product pages, they end up with all those link tags in the final page. This is causing a lot of problems for SEO.

orphaned style tags

I'm using this module to temporarily add some extra global style - in this case disabling scrolling on the html body, which can be useful in some cases like when a modal or nav is being displayed on top of the main content.

For example, my header/nav component has something like this (written in script setup style):

const isMobileNavOpen = ref(false);
function toggleMobileNav() { isMobileNavOpen.value = !isMobileNavOpen.value; }

// add extra body style to lock scrolling on main content while mobile nav is open
useHead({
  style: [{
    children: computed(() => (isMobileNavOpen.value ? 'body { overflow: hidden; }' : '')),
  }],
});

This works and the style is added/removed as the nav is toggled, locking body scroll as it should.

The problem is that if the component is unloaded, it is not cleaning up after itself and removing the extra style tag.
This happens for example if I navigate to a different route that uses a different layout that does not contain this nav component.

I'm able to fix it by adding a onBeforeUnmount handler like so:

onBeforeUnmount(() => {
  useHead({ style: [{ children: '' }] });
});

but to me this was unexpected. I would have thought that any component that uses useHead would clean up after itself before unloading.

Please advise if this is expected or a bug that needs addressing. If it is a bug I can try to dig in and get it fixed.

Thanks!

Can I remove the `data-XXX` attributes?

I saw some extra data-XX attributes was generated via renderHeadToString:

<html class='home-page' data-head-attrs='class'>
<head>
  <title>home page</title>
  <meta name='head:count' content='0'>
</head>
<body class='home-page-body' data-head-attrs='class'>
<div id='app'>
  <div>hi
    <main>world</main>
  </div>
</div>
</body>
</html>

in this example: data-head-attrs,<meta name='head:count' content='0'>

what's the purpose of this? Can I remove them?

Build with vue 3.2.34

vuejs/core#5416 added two new arguments to the DefineComponent type, causing the emitted type from earlier versions to throw

node_modules/@vueuse/head/dist/index.d.ts:45:149 - error TS2344: Type 'VNodeProps & AllowedComponentProps & ComponentCustomProps' does not satisfy the constraint 'ComponentProvideOptions'.
  Type 'VNodeProps & AllowedComponentProps & ComponentCustomProps' is not assignable to type 'ObjectProvideOptions'.
    Index signature for type 'string' is missing in type 'VNodeProps & AllowedComponentProps & ComponentCustomProps'.

45 declare const Head: vue.DefineComponent<{}, () => null, {}, {}, {}, vue.ComponentOptionsMixin, vue.ComponentOptionsMixin, vue.EmitsOptions, string, vue.VNodeProps & vue.AllowedComponentProps & vue.ComponentCustomProps, Readonly<vue.ExtractPropTypes<{}>>, {}>;
                                                                                                                                                       ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

How to use dynamic values?

Hi,
Probably not an issue but testing this out and can not figure out how add dynamic values in meta.

Base example:

import { defineComponent, computed, reactive } from 'vue'
import { useHead } from '@vueuse/head'

export default defineComponent({
  setup() {
    const siteData = reactive({
      title: `My website`,
      description: `My beautiful website`,
    })

    useHead({
      // Can be static or computed
      title: computed(() => siteData.title),
      meta: [
        {
          name: `description`,
          content: computed(() => siteData.description),
        },
      ],
    })
  },
})

How can you add a variable in title, like:

import { defineComponent, computed, reactive } from 'vue'
import { useHead } from '@vueuse/head'

export default defineComponent({
  setup() {
    const siteData = reactive({
      title: this.title, // Here
      description: `My beautiful website`,
    })

    useHead({
      // Can be static or computed
      title: computed(() => siteData.title),
      meta: [
        {
          name: `description`,
          content: computed(() => siteData.description),
        },
      ],
    })
  },
})

Compile Error

I am getting the following error when attempting to compile our code
ERROR in ../node_modules/@vueuse/head/dist/index.mjs 349:27-42 Can't import the named export 'defineComponent' from non EcmaScript module (only default export is available)

I followed the readme instructions for npm install and then the standard import of the code.
import { createHead } from '@vueuse/head'

"@vueuse/head": "^0.6.0"
"webpack": "^4.46.0"

running Node: v14.17.1

Thanks!

share do not recognize head meta properties

Hello.

I'm using vue3 and composition api im my project.

I managed to add dynamic meta tags to the html head section:
image

However, the link share on social netwroks is not fecthing and previewing these contents. Any clue of what is happening?

In facebook share debugger tool i have at least a warning:
Inferred Property
The 'og:image' property should be explicitly provided, even if a value can be inferred from other tags.

But this property is defined. I'm thinking when the facebook scraps my page, these properties aren't yet on the page...

Anyone can help me understand what is going on and how to solve this?

ampersands get escaped in URLS

  renderHeadToString({
    headTags: [
      {
        tag: 'script',
        props: {
          async: true,
          hid: 'maps-googleapis',
          src: 'https://maps.googleapis.com/maps/api/js?key=example&libraries=places',
        },
      },
    ],
  }).headTags

results in:

<script async hid="maps-googleapis" src="https://maps.googleapis.com/maps/api/js?key=example&amp;libraries=places"></script><meta name="head:count" content="1">

https://github.com/vueuse/head/blob/main/src/stringify-attrs.ts#L2-L32

https://github.com/vueuse/head/blob/main/src/index.ts#L347-L362

Here's a reproduction.

ReferenceError: Node is not defined

I'm using @vueuse/head v0.6.0 with vite-ssg and was confused with the following error message that killed the build script because it refers to Node (which I thought meant the language but actually refers to a variable called Node in this case).

ReferenceError: Node is not defined
    at /[..]/node_modules/@vueuse/head/dist/index.js:202:55
    at Array.forEach (<anonymous>)

The following code in the built script in dist is the culprit:

  oldElements.forEach((el) => {
    if (el.nextSibling && el.nextSibling.nodeType === Node.TEXT_NODE) {
      el.nextSibling.remove();
    }
    el.remove();
  });

There is no Node.TEXT_NODE imported or defined anywhere so if run this code will fail (although it seems to work fine in the browser at least w/ Vite dev server). This was introduced in #28. My workaround is to use npm version 0.5.1 which works fine, the current 0.6.0 doesn't.

<Head> component with v-html directive

Hello.
I'm using RankMath - a well known WordPress SEO plugin.
The plugin gives me a string that contains all the html that needs to go in the section of the page.
e.g "<title>some title</title>".
As i mentioned the data im getting from the plugin is a string of html elements.
When i try to pass the string to the component like so:

It doesn't work. Anyway to fix this? Or some other way to achieve the desired result?

How to get Head?

I am working on a SSR sharing plugin so that the title is generated on server side.
the case is setting head in one component while getting head on another component.
How can I achieve that?

I can get the title with this.

useNuxtApp().vueApp.config.globalProperties.$head.headTags.filter(x => x.tag === 'title').filter(x => x.tag === 'title').reverse()[0].props.children

Any simpler way to get it?

Replace meta tags if they already exist

In my index.html I have set up some meta tags as a fallback if my prerenderer fails (for some reason). When I use @vueuse/head and I set a meta tag I have already set in my HTML file, I end up with duplicate meta tags. Since new meta tags are created at the end of the head tag, duplicate tags technically won't matter but I find it a bad practice. Could you please support the replacement of tags if they already exist?

useHead causes flickering when hydrating SSR-rendered page on Nuxt

Original issue is nuxt/nuxt#14271

Environment

  • Operating System: Linux
  • Node Version: v16.14.0
  • Nuxt Version: 3.0.0-rc.4
  • Package Manager: [email protected]
  • Builder: vite
  • User Config: modules, css
  • Runtime Modules: @nuxtjs/[email protected]
  • Build Modules: -

Reproduction

Use useHead to assign some CSS classes to body, and then visit the page:

<script setup lang="ts">
useHead({
  bodyAttrs: {
    class: 'accent-yellow dark-zinc dark'
  }
});
</script>
useHead-flicker.mp4

Describe the bug

SSR correctly generates classes on body, then on hydration they are removed and then added again, resulting in a very noticeable flicker, especially when these classes are used to switch between dark and light styles of whole page.

New feature: head components

Might be nice to create Vue component/s to allow users to interact with the head as managed by @vueuse/head within the <template>. Is this on your roadmap/would you welcome adding this to the project?

Way to de-duplicate existing meta inside of html head

When using the (seemingly now-deprecated) vue-meta, there was a way to tie into existing meta tags when mounting vue.

Specifically, you could add an attribute, e.g. vmid ( see https://vue-meta.nuxtjs.org/faq/#unique-metadata )

<meta name="description" data-vmid="some_unique_value" content="This is blue.">

And then when using vue w/ vue-meta, you could reference this meta like so:

head() {
  return {
    meta: [{
      'vmid': 'some_unique_value',
      'name': 'description',
      'content': 'This is red.'
    }]
  };
}

And the meta tag would be replaced, as you would expect.

However, in vueuse/head, I don't see that such an option exists. I see that there is a reference to "key", but this only works if the meta you are replacing was created using vueuse/head in the first place, and not for previously existing meta.

Isnt updating tags.

Hi, I'm using vue-class-component and I have this:

@options({
components: {
HomeComponent,
},
setup() {
useHead(() => ({
title: Spencer: Home,
meta: [
{
name: description,
content: hey,
},
],

}))

}
})
export default class Home extends Vue {}

But, the title isn't changing. Any ideas? Embeds don't work either

tags are removed before being refreshed on load

This line removes all link tags that aren't controlled by vueuse/head:

oldElements.forEach((t) => t.parentNode?.removeChild(t))

If I remove that then this section does the same thing when run by vite-ssg because querySelector('link[key="null"]') just returns the first <link> due to a jsdom bug:

head/src/index.ts

Lines 213 to 218 in 392e8c8

const uncontrolled = head.querySelector(
`${t.tagName.toLowerCase()}[${key.name}="${key.value}"]`,
)
if (uncontrolled) {
uncontrolled.parentNode?.removeChild(uncontrolled)
}

Originally posted by @KaelWD in #45 (comment)

"You may forget to apply app.use(head)"

Hey so maybe a stupid question, but I am a bit new to Vue.

I am getting an error "You may forget to apply app.use(head)" but my main.js code looks like this;

import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import { projectAuth } from './firebase/config';
import { createHead } from '@vueuse/head';

//wait firebase to get user
let app;
const head = createHead()

projectAuth.onAuthStateChanged(() => {
  if (!app) {
    app = createApp(App).use(router, head).mount("#app");
  }
});

my .use has (router) previously, so added (router, head) is this correct? IF so, any ideas what my error may be in regards to?

Uncaught ReferenceError: defineComponent is not defined (with vite & vite-ssr)

I'm using a repo based on vitesse-ssr-template and @vueuse/head is getting the following when attempting to define the Head component:

Uncaught ReferenceError: defineComponent is not defined

I've tested this with both vite and vite-ssr, and the above happens in both on the client, but running with vite-ssr will product valid HTML on the server (i.e. the vite on does not render; the vite-ssr one renders, but is non-interactive)

Updating vitesse-ssr-template's dependencies should be sufficient to reproduce, but here's my package.json:

{
  // ...
  "engines": {
    "node": ">=14"
  },
  "scripts": {
    "bi": "bi --pm pnpm",
    "fetch": "node ./scripts/fetch-metadata",
    "gen": "node ./scripts/generate-entities",
    "dev": "vite-ssr --port 3333 --open",
    "dev:spa": "vite --port 3333 --open",
    "clean": "rm -rf dist; rm -rf api/renderer",
    "build": "pnpm clean; cross-env NODE_ENV=production vite-ssr build; ./scripts/move-dist.sh",
    "preview": "vc dev"
  },
  "dependencies": {
    "@apollo/client": "^3.3.16",
    "@replygirl/tc": "^3.0.0",
    "@vue/reactivity": "^3.0.11",
    "@vue/server-renderer": "^3.0.11",
    "@vueuse/core": "^4.9.1",
    "@vueuse/head": "^0.5.1",
    "axios": "^0.21.1",
    "breeze-client": "^2.1.1",
    "element-plus": "^1.0.2-beta.41",
    "hash-sum": "^2.0.0",
    "node-fetch": "^2.6.1",
    "nprogress": "^0.2.0",
    "pluralize": "^8.0.0",
    "prism-theme-vars": "^0.2.2",
    "querystring": "^0.2.1",
    "vite-ssr": "^0.8.0",
    "vue": "^3.0.11",
    "vue-i18n": "^9.1.6",
    "vue-router": "^4.0.6",
    "vue3-google-map": "^0.7.6"
  },
  "devDependencies": {
    "@antfu/eslint-config": "^0.6.4",
    "@iconify/json": "^1.1.337",
    "@intlify/vite-plugin-vue-i18n": "^2.1.2",
    "@replygirl/curse": "^3.0.0-beta.0",
    "@rollup/plugin-graphql": "^1.0.0",
    "@types/axios": "^0.14.0",
    "@types/btoa": "^1.2.3",
    "@types/dotenv-flow": "^3.1.0",
    "@types/eslint": "^7.2.10",
    "@types/eslint-config-prettier": "^6.11.0",
    "@types/eslint-plugin-prettier": "^3.1.0",
    "@types/hash-sum": "^1.0.0",
    "@types/node": "^14.14.43",
    "@types/node-fetch": "^2.5.10",
    "@types/nprogress": "^0.2.0",
    "@types/pluralize": "^0.0.29",
    "@types/prettier": "^2.2.3",
    "@types/pug": "^2.0.4",
    "@types/rimraf": "^3.0.0",
    "@typescript-eslint/eslint-plugin": "^4.22.0",
    "@vercel/node": "^1.10.0",
    "@vitejs/plugin-vue": "^1.2.2",
    "@vue/compiler-sfc": "^3.0.11",
    "better-install": "^0.1.0",
    "breeze-entity-generator": "^1.0.0",
    "btoa": "^1.2.1",
    "cross-env": "^7.0.3",
    "dotenv-flow": "^3.2.0",
    "eslint": "^7.25.0",
    "eslint-config-prettier": "^8.3.0",
    "eslint-plugin-prettier": "^3.4.0",
    "markdown-it-prism": "^2.1.6",
    "pnpm": "^5.18.9",
    "prettier": "2.2.1",
    "pug": "^3.0.2",
    "rimraf": "^3.0.2",
    "ts-node": "^9.1.1",
    "type-fest": "^1.0.2",
    "typescript": "^4.2.4",
    "vite": "^2.2.3",
    "vite-plugin-components": "^0.8.4",
    "vite-plugin-icons": "^0.5.0",
    "vite-plugin-md": "^0.6.3",
    "vite-plugin-pages": "^0.10.0",
    "vite-plugin-pwa": "^0.7.3",
    "vite-plugin-vue-layouts": "^0.2.2",
    "vite-plugin-windicss": "^0.14.6",
    "vite-ssg": "^0.9.3"
  },
 //  ...
}

How to add a script tag with script text

I am finding it impossible to add a <script> tag to the head that contains actual script text rather than just a src attribute.

I need to add something like the following:

script: [
{
       type: "application/ld+json",
       text:
      {
        "@context": "https://schema.org",
        "@type": "Product",
        "description": "I am product A",
        }
 }
]

How can I add a <script> tag with text content so it will render like such:

<script type="application/ld+json">   {
        "@context": "https://schema.org",
        "@type": "Product",
        "description": "I am product A",
        }
</script>

SSR dynamic meta data

I have problem with SSR and dynamic meta data loading. For example I have awaiting function getTitle() and need to set page title after request complete. In console log title value in reactive state is correct, but page title is not - there is still old the value.

Here is my code:

async setup() {
    const siteData = reactive({
      title: `My website`,
      description: `My beautiful website`,
    });
    
    useHead({
      title: computed(() => siteData.title),
      meta: [
        {
          name: `description`,
          content: computed(() => siteData.description),
        },
      ],
    })

    //Fetch request simulator...
    siteData.title = await getTitle();
    console.log(siteData.title); //Here is correct value
  }

How can I set dynamic meta data? Thank you for your time.

invalid tags generated by `renderHeadToString`

Some sample HTML generated by renderHeadToString:

<title>Welcome to my startup</title><link rel="stylesheet" href="https://fonts.xz.style/serve/inter.css"/><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@exampledev/[email protected]/new.min.css"/><script preload="" src="/analytics.js" async="" defer=""/>

In particular, self closing <script /> tag will cause the rest of the document not to be rendered at all in some browsers. All these head elements can just be rendered without the slash.

Using v-for inside of <Head> tag to define meta list

I'm trying to define <meta /> tags using a v-for

<template>
  <Head>
    <title>{{ metaInfo.title }}</title>
    <meta
      v-for="tag in metaList"
      :key="tag.name"
      :name="tag.name"
      :content="tag.content"
    />
  </Head>
</template>

<script>
{
  data() {
    return {
      metaList: [{
        name: "test",
        content: "test",
      }],
    };
 },
}
<script>

This produces no meta. If I remove the v-for and use directly indices, it starts to work.
Any idea of how can achieve this?
Thanks!

Work package with i18n

Is it possible to reactive change meta tag content when changing language?
P.S: Not working with reactive func

Can't get meta description to appear

What am I doing wrong here? Why am I not seeing the <meta name="description" content="My beautiful website" /> in my source code?

Here's how I am setting up the code:

<template>
  <nav class="p-5 bg-green-400 text-white mb-10">
    <router-link :to="{ name: 'Home' }">Snazzy Fake Blog</router-link>
  </nav>
  <div class="container">
    <router-view></router-view>
  </div>
</template>

<script setup>
import { defineComponent, reactive, computed } from 'vue'
import { useHead } from '@vueuse/head'
const siteData = reactive({
  title: `My website`,
  description: `My beautiful website`
})
useHead({
  // Can be static or computed
  title: computed(() => siteData.title),
  meta: [
    {
      name: `description`,
      content: computed(() => siteData.description)
    }
  ]
})
</script>

FOUC on navigation with nested route with custom CSS and Style on parent component

When using useHead on parent and children component with vue-router, everything works fine but during transition, vueuse/head re-trigger parent head and cause FOUC.

Reproduction :
https://codesandbox.io/s/nameless-grass-b904r
Note : when opening Chrome dev tool, you can also see in Network Tab google font is loaded when navigate from / to /about. If the FOUC is not visible, because the network is too fast, you can throttle network

Apart from that, vueuse/head is incredible, I use for SSR project and I appreciate all the work of this project !

Cheers
JM

support for merging `<head>` and `<body>` attrs

At the moment we can't merge classes, for example:

useHead({
  htmlAttrs: { class: 'first-class' }
})
useHead({
  htmlAttrs: { class: 'second-class' }
})

Sandbox

In this case there will be only one class applied to <html> rather than merging the two, which is what I would expect...

How to use useHead in watch? router hooks?

Hello. I know this maybe not connected with this plugin. But I can't make it work with router.
I have 30+ routes

I would like to get route.name and pass to "title". I tried diff options but none doesn't work.
After this in some components I will change to specific attr

<template>
  <animated-router-view />
</template>

<script lang="ts" setup>
import AnimatedRouterView from '@/components/AnimatedRouterView.vue'
import { useRoute } from "vue-router";
import { useHead } from "@vueuse/head";
import { computed, watch } from "vue";

const route = useRoute()

// this option works
// useHead({
//   title: 'asd',
// })


// option via watch doesn't work
// with deep true, computed, it doesn't work
watch(route,
  (to) => {
  console.log(to.name) // work
  
  // doesn't work
  useHead({
    title: 'asd',
  })
  }
)
</script>

typing error: computed

i use vue@^3.2.13 and @vueuse/head@^0.6.0, there is reference error while typing computed.
it's not show but i forgot what version of vue that i used before, but after i upgrade this error show up.


Type 'ComputedRef<string | undefined>' is not assignable to type 'MaybeRef<string> | undefined'.
  Type 'ComputedRef<string | undefined>' is not assignable to type 'Ref<string>'.ts(2322)
<script setup lang="ts">
import { computed } from "vue";
import { useHead } from "@vueuse/head";

const data = reactive<IMangaResult>({});

useHead({
  title: computed(() => data.title),
});
</script>

Option for ordering in head? font faces loaded before fonts are loaded, results in annoying warning

Is there any option to define an order of the head stuff? Or to define specific stuff to be loaded at the end of head?

I have the problem, that i use vueuse/head for my font face definitions in style tag and also for preloading of the fonts.
But the font faces get loaded before the fonts. That results in following warning

Bildschirmfoto 2022-03-14 um 10 22 28

Because there is no font face definition AFTER the font loading.
It can be fixed when the style tag with font face definition is at the very end of head. But i don't find a configuration how to achieve this with vueuse/head.

I think there are use cases where the order in the head can be important.

Note: using vueuse/head with SSR

Ability to add arbitrary tags and comments into <head>

Currently useHead() implements a whitelist of tags that can be added into the <head> element. I need to add an ESI tag or an HTML comment to load assets originating from another service. These needs to be added conditionally, so even if Nuxt 3 would allow overriding its app.html a solution within useHead() would be best.

To illustrate, I am currently using this hack:

<template>
    <Style v-if="isServer" :children="myCustomTag" />
    <NuxtPage/>
</template>

<script setup>
const isServer = process.server
const myCustomTag = ' </style> <!--esi <esi:include src="/foo/bar" />--> <style> '
</script>

This inserts the comment at the cost of two empty <style> tags. Obviously this can only be a temporary workaround.

I am unsure what the best API would be, maybe just teleport all child elements of <Head> into <head>. E.g:

<Head>
  <!--esi <esi:include src="/foo/bar" />--> 
</Head>

Meta tags are "deduped" based on property name only

According to https://ogp.me/ "If a tag can have multiple values, just put multiple versions of the same tag on your page."

In my use case I want to add multiple tags for the video pages of my website and I am adding these values to the meta array. The issue is that only 1 of the properties is added due to the fact that the property names are the same.

I have tested this by adding a suffix to each property name and all of the elements are added, although they are no longer valid OG tags.

<meta property="og:video:tag1" content="Bene Gesserit">
<meta property="og:video:tag2" content="Blade Runner 2049">
<meta property="og:video:tag3" content="Coming Soon">

Currently I only get

<meta property="og:video:tag" content="Coming Soon">

The desired outcoume would look like below :

<meta property="og:video:tag" content="Bene Gesserit">
<meta property="og:video:tag" content="Blade Runner 2049">
<meta property="og:video:tag" content="Coming Soon">

I would suggest that a check on the content property value is performed during the deduplication process in order to allow for the desired output as above.

Dynamic title component memory leak

I found something special in using dynamic reference title in template component. Look at this:

<template>
       <div>
            <Head>
                <title> {{ somethingComputedObject.prop }} </title>
            </Head>
            
            .....
            
       </div>
</template>

....

The server monitor show memory leaks in apache benchmark test. Works fine without Head component, or with static text (not reference property). Composition API hook looks well too - I've analyzed problem only in component.

Can you check it please? Thank you.

[Feature Request] Handle titleTemplate like vue-meta

Hi,
It could be really cool to have a titleTemplate like vue-meta, to be able to set a part of title for each page, and a global part.

For now, I've just made my own use head that just do that:

import { useHead as originalUseHead, HeadObject } from '@vueuse/head'

export const useHead = (head: HeadObject) => originalUseHead({
  ...head,
  title: `${head.title} - MyProject`
})

But it can't be customized in the app.

Thanks for your amazing work,
Mathieu.

feat: add suffix to all titles

Feature request

I'd like a way to add a suffix to all titles automatically.

In my use-case, every title from my site should be suffixed with the website name:

  • Home | privatenumber
  • Blog | privatenumber
  • Contact | privatenumber

Technical approach

I'm wondering if it would make sense to add an API to createHead():

const head = createHead({
    title: (titleValue) => titleValue + ' | privatenumber'
})

app.use(head)

dynamic data for title fetched by created()

how can i set my title after data fetched by created() in vue3. my structure is:

data () {
    return {
      article: null,
    }
  },
setup() {
    const siteData = reactive({
      title: this.article.title
    })

    useHead({
      title: computed(() => _title??_)
    })
  },
async created () {
 query({})
.then () = {
this.article = data.articleByID
}
}

make API better

Most of the time, we set page title after async fetch, so we must use computed:

title: computed(() => siteData.title)

why not provide a function to set the reactive object? like this:

import { useHead } from '@vueuse/head'
export default defineComponent({
  async setup() {
    const setHead = useHead()

    setHead({
      title: 'static string',
      meta: [
        {
          name: 'description',
          content: 'static string',
        },
      ],
    })
  },
})

And most of the time, we must set title, description and keywords for SEO, so I think we can make it more convenient:

setHead({
  title: 'static string',
  description: 'static string',
  keywords: 'static keywords',
  meta: [
    // ...
  ],
  script: [
    // ...
  ]
})

`vueuse/head` doesn't support events when creating an element

Hi everybody.
I recently worked on new features that bring script loading strategy to the Nuxt. The problem is when I add some events to the script component (provided by nuxt as sugar syntax of useMeta), it turned into attributes and prints the event function string on the element.

<script src="./mock.js?t=49" strategy="immediate" onload="function() { console.log('loaded')"></script>

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.