页面

页面是通过在 src/routes 目录中添加新的 index.tsx 文件创建的。页面导出一个 default Qwik 组件,该组件将被渲染为页面的内容。

src/routes/some/path/index.tsx
import { component$ } from '@builder.io/qwik';
 
// Notice the default export
export default component$(() => {
  return <h1>Hello World!</h1>;
});

页面和端点之间的唯一区别在于,端点只导出一个 onRequestonGetonPostonPutonDeleteonPatchonHead 函数,该函数将用于处理传入的请求。

head 导出

每个页面都可以导出一个 head 属性(或函数),该属性(或函数)返回一个 DocumentHead 对象。DocumentHead 对象用于解析页面的标题,以及元数据、链接和样式。

此 API 允许您设置页面的标题,以及元数据、开放图谱、Twitter 标签和链接。这对于 SEO 和社交分享很有用。

src/routes/about/index.tsx
import { component$ } from '@builder.io/qwik';
import type { DocumentHead } from '@builder.io/qwik-city';
 
export default component$(() => {
  return <h1>About page</h1>;
});
 
export const head: DocumentHead = {
  // This will be used to resolve the <title> of the page
  title: 'About page',
  meta: [
    {
      name: 'description',
      content: 'This is the about page',
    },
    // Open graph
    {
      property: 'og:title',
      content: 'About page',
    },
    {
      property: 'og:description',
      content: 'This is the about page',
    },
  ],
  links: [
    {
      rel: 'canonical',
      href: 'https://example.com/about',
    },
  ],
};

上面的示例设置了标题,以及一些 开放图谱 元数据和 规范链接

HTML 将 <head> 标签放置在 <html> 中的第一个元素(在 HTML 内容的最顶部)。<head> 部分不是您的路由组件直接渲染的内容,因为它会破坏 HTML 流。

查看 useDocumentHead() 以从您的组件内部读取和使用 DocumentHead 对象。

动态头部

您还可以导出一个返回 DocumentHead 对象的函数,允许您以编程方式设置 <title><meta><link> 标签。

这使您能够使用 routeLoader$()routeAction$() 中的数据配置 <head>,包括标题、元数据或链接。

我们可以使用 resolveValue 方法在 head 函数中获取 routeLoader$()routeAction$() 的值。

src/routes/jokes/[jokeId]/index.tsx
import { component$ } from '@builder.io/qwik';
import { routeLoader$ } from '@builder.io/qwik-city';
import type { DocumentHead } from '@builder.io/qwik-city';
 
export const useJoke = routeLoader$(async (requestEvent) => {
  // Fetch a joke from a public API
  const jokeId = requestEvent.params.jokeId;
  const response = await fetch(`https://api.chucknorris.io/jokes/${jokeId}`);
  const joke = await response.json();
  return joke;
});
 
// Now we can export a function that returns a DocumentHead object
export const head: DocumentHead = ({resolveValue, params}) => {
  const joke = resolveValue(useJoke);
  return {
    title: `Joke "${joke.title}"`,
    meta: [
      {
        name: 'description',
        content: joke.text,
      },
      {
        name: 'id',
        content: params.jokeId,
      },
    ],
  };
};

嵌套布局和头部

在高级情况下,布局 可能希望修改已解析的文档头部的文档标题。在下面的示例中,页面组件返回标题 Foo。包含的布局组件可以读取页面文档头部的值并修改它。在此示例中,布局组件正在向标题添加 MyCompany - ,因此渲染后的标题将为 MyCompany - Foo。堆栈中的每个布局都有机会返回一个新值。

──src/
  └─routes/
    ├─index.tsx
    └─layout.tsx
src/routes/index.tsx
export const head: DocumentHead = {
  title: `Foo`,
};
src/routes/layout.tsx
export const head: DocumentHead = ({ head }) => {
  return {
    title: `MyCompany - ${head.title}`,
  };
};

Google 结构化数据

此示例集成了 Google 结构化数据,它通过向 Google 提供有关页面含义的明确线索来提供帮助。如果您想嵌入自定义 JavaScript 代码,最好使用 Partytown 延迟加载它。但是,有时您被迫立即加载它们。以下示例说明了这一点。

src/routes/about/index.tsx
import { component$ } from '@builder.io/qwik';
import type { DocumentHead } from '@builder.io/qwik-city';
 
export default component$(() => {
  return <h1>About page</h1>;
});
 
export const head: DocumentHead = {
  scripts: [
    {
      props: {
        type: "application/ld+json",
      },
      script: JSON.stringify({
        "@context": "https://schema.org",
        "@type": "ItemList",
      }),
    },
  ],
};

上面的示例设置了一些 结构化数据标记

注意:您需要更改 router-head 组件以渲染 head.scripts

src\components\router-head\router-head.tsx
import { component$ } from "@builder.io/qwik";
import { useDocumentHead, useLocation } from "@builder.io/qwik-city";
 
export const RouterHead = component$(() => {
  const head = useDocumentHead();
  const loc = useLocation();
 
  return (
    <>
      <title>{head.title}</title>
 
      {/* add this  */}
      {head.scripts.map((s) => (
        <script key={s.key} {...s.props} dangerouslySetInnerHTML={s.script} />
      ))}
    </>
  );
});
 

贡献者

感谢所有帮助改进此文档的贡献者!

  • adamdbradley
  • manucorporat
  • Oyemade
  • the-r3aper7
  • mhevery
  • nnelgxorz
  • igorbabko
  • solamichealolawale
  • mrhoodz
  • VinuB-Dev
  • nhayhoc
  • gioboa
  • jemsco