【问题标题】:Deno, Fresh framework - html template manipulationDeno,Fresh 框架 - html 模板操作
【发布时间】:2022-10-08 18:06:49
【问题描述】:

我最近在玩新的 deno 框架,一切都很棒,但在某个时候,我意识到不可能将任何额外的元数据添加到页面标题标签。基本上我想做两件事:

  1. 添加标题标签
  2. 从我的静态目录链接一些 css 文件

    您知道如何实现这一目标吗? 在理想的世界中,我希望能够提供我自己的 html 模板,或者至少有一些灵活的方式来操作提供的固定模板。 我确实在 Fresh 源文件中找到了一些代码 sn-p,它基本上是前面提到的固定 html 模板,但不幸的是它看起来对我来说不是可定制的 - 只有可变元素是opts.headComponents,但我不确定我是否可以影响它。

    export interface TemplateOptions {
      bodyHtml: string;
      headComponents: ComponentChildren[];
      imports: (readonly [string, string])[];
      styles: string[];
      preloads: string[];
      lang: string;
    }
    
    export function template(opts: TemplateOptions): string {
      const page = (
        <html lang={opts.lang}>
          <head>
            <meta charSet="UTF-8" />
            <meta http-equiv="X-UA-Compatible" content="IE=edge" />
            <meta name="viewport" content="width=device-width, initial-scale=1.0" />
            {opts.preloads.map((src) => <link rel="modulepreload" href={src} />)}
            {opts.imports.map(([src, nonce]) => (
              <script src={src} nonce={nonce} type="module"></script>
            ))}
            <style
              id="__FRSH_STYLE"
              dangerouslySetInnerHTML={{ __html: opts.styles.join("\n") }}
            />
            {opts.headComponents}
          </head>
          <body dangerouslySetInnerHTML={{ __html: opts.bodyHtml }} />
        </html>
      );
    
      return "<!DOCTYPE html>" + renderToString(page);
    }
    

【问题讨论】:

    标签: javascript deno preact freshjs


    【解决方案1】:

    我在一些fresh issue 中找到了答案。 head 和 body 标签的编辑可以通过 JSX 来完成,就像这样:

    /** @jsx h */
    import {h} from 'preact';
    import {PageProps} from '$fresh/src/server/types.ts';
    import {tw} from '@twind';
    
    export const Head = () => (
        <head>
            <title>My title</title>
        </head>
    );
    
    export default function LoginPage(props: PageProps) {
        return (
            <div class={tw`w-screen h-screen flex justify-center bg-green-900`}>
                <Head />
            </div>
        )
    }
    

    猜猜这种做事方式来自 preact 还是 SSR?从我的角度来看,这有点奇怪 - 将头部/身体注入一些 div,不是很直观。

    编辑

    找到了更好的解决方案,因为前面给出的答案仍然导致元标记被放在正文标记内。

    我们可以用_app.tsx这基本上是每个渲染路线的包装器并使用特殊的来自新库的组件。这是填充的正确方法opts.headComponents来自固定 html 模板的字段(有问题)。不幸的是,似乎没有这方面的文档。取自新鲜tests 的示例:

    /** @jsx h */
    /** @jsxFrag Fragment */
    import { Fragment, h } from "preact";
    import { Head } from "$fresh/runtime.ts";
    import { AppProps } from "$fresh/server.ts";
    
    export default function App(props: AppProps) {
      return (
        <>
          <Head>
            <meta name="description" content="Hello world!" />
          </Head>
          <props.Component />
        </>
      );
    }
    

    【讨论】:

    • 不,它与 Preact 或 Preact 的渲染到字符串完全无关。这严格来说是 Fresh/Deno。
    • 您在回答中提出问题。请不要将此添加为答案,而是使用您找到的信息编辑您的问题并重新表述您的问题。
    【解决方案2】:

    您可以使用@Harrel 编辑的答案。但是,如果您希望在不同页面上向&lt;head&gt; 添加动态内容,例如&lt;title&gt;,您也可以在各个页面中使用&lt;Head&gt; 组件。 &lt;Head&gt; 组件的子组件将堆叠,因为该组件是作为上下文实现的,正如我们从源代码中看到的那样

    您可以像这样在每个页面中输入&lt;title&gt;

    _app.tsx 中的元标记和样式表就像这样

    希望这可以帮助某人。

    【讨论】: