使用钩子在Svelte中设置主题
#javascript #教程 #svelte #theme

这是Secure Authentication in Svelte using Hooks的后续文章,以扩展我们的挂钩文件。如果您正在寻找一种在Sveltekit应用中实现身份验证的方法,请肯定地查看该文章。

如果您曾经构建了一个具有多个主题的站点,那么您有可能会遇到令人讨厌的问题,即在计算主题值的客户端之前让网站闪存。在本教程中,我们将设置hooks.server.js文件,以允许在发送给客户端之前处理一个动态主题

初始设置

如果您还没有hooks.server.js文件,则最基本的版本如下:

// hooks.server.js
export const handle = async({event, resolve}) => {
  const response = await resolve(event);

  return response;
}

这在上一篇文章中解释了这一点,但这是任何新读者的进修:

event属性包含与文件请求有关的所有信息。这包括用户的cookie,浏览器HTTP标头和特定请求的URL。您可以在此处阅读更多Indepth文档:SvelteKit Hooks

第二个项目resolve是创建完成HTML的函数。

我们的handle()函数是await resolve(event)调用。这是一件Sveltekit的东西,本质上告诉服务器在将HTML发送给客户端之前就可以构建HTML了。返回该response值以正常方式呈现页面。

在本教程中,我们将使用一个简单的HTML数据属性来处理将使用CSS的。在您的app.html页面中,继续将其添加到您的<html>标签中:

<html lang="en" data-theme="">

这就是我们为HTML页面所需的所有设置。继续关闭它,让我们打开我们的hooks.server.js文件。

现在,我们要修改我们的resolve()功能以查找字符串data-theme=""并用用户的主题cookie值替换。我们可以这样做:

// hooks.server.js
export const handle = async({event, resolve}) => {
  const response = await resolve(event, {
    // Processing will go here
  });

  return response;
}

第一步是将对象添加为resolve()的第二个属性。在此处,我们可以调用Svelte对象属性transformPageChunk,并将其传递给函数。看起来像这样:

// hooks.server.js
export const handle = async({event, resolve}) => {
  const response = await resolve(event, {
    transformPageChunk: ({html}) => {
      // This section will modify the HTML 
      // before being returned to the client
    }
  });

  return response;
}

我们想首先检查用户的主题cookie是否存在。这可能是没有cookie的新用户,也可以是现有用户。一种简单的方法是检查从root handle()函数传递的event.cookies

// hooks.server.js
export const handle = async({event, resolve}) => {
  const response = await resolve(event, {
    transformPageChunk: ({html}) => {
      // This section will modify the HTML 
      // before being returned to the client
      let currentTheme = cookies.get("theme");

      // Make sure the cookie was found, if not, set it to dark
      if(!currentTheme) {
        currentTheme = "dark";
        cookies.set("theme", currentTheme)
      }
    }
  });

  return response;
}

此值如果不存在,将返回null,因此添加默认值很有用。我们还可以将其作为为所有新用户设置主题cookie的机会。在上面的代码中,我们将默认值设置为dark

现在我们已经准备好主题值,我们可以在发送给客户端之前更新HTML。最简单的方法是在整个HTML上使用replace() JavaScript函数。请注意,replace()是无损的,因此,如果要进行其他处理,则必须将其保存到新变量中。

// hooks.server.js
export const handle = async({event, resolve}) => {
  const response = await resolve(event, {
    transformPageChunk: ({html}) => {
      // This section will modify the HTML 
      // before being returned to the client
      let currentTheme = cookies.get("theme");

      // Make sure the cookie was found, if not, set it to dark
      if(!currentTheme) {
        currentTheme = "dark";
        cookies.set("theme", currentTheme)
      }

      return html.replace(`data-theme=""`, `data-theme="${currentTheme}"`);
    }
  });

  return response;
}

这样,在发送到客户端之前,您的主题现在正在处理。不再闪烁!

CSS示例

如果您很好奇如何使用CSS访问此问题,则可以使用CSS变量这样:

:root {
  --body: #fff;
  --text: #000;
}

[data-theme='dark']:root {
  --body: #000;
  --text: #fff;
}

body {
  background-color: var(--body);
  color: var(--text);
}