Skip to content

🔥 (#82) 有关《Mastering Nuxt 3》发布日期的信息

2022 年 10 月

最近怎么样?

《Mastering Nuxt 3》将在两周后的 10 月 25 日 发布!

届时会有一个很大的发售折扣,等到发售的时候我会发送给你链接。

所以请留意这一点!

另一则新闻,我从新冠中恢复了。疫情发生了两年半,我还是感染了。

当我恢复后,我又花了几天的时间来补觉。

现在时候继续努力工作了!

祝你度过美好的一周!

—Michael

🔥 在 Tailwind 中定义你自己的 class 工具方法

Tailwind 里最好的一部分功能就是定义你自己的工具方法。

我需要一个 z-index 负值,单 Tailwind 并没有提供,所以我写了一个:

@layer utilities {
  .-z-1 {
    z-index: -1;
  }
}

通过 @layer utilities { ... } 包装的内容会被作为一个 class 方法 添加进 Tailwind

如果你需要使用一个自定义 class 方法来处理响应式,处理 hover 状态,或者暗黑模式,都可以在 v3.0 里实现!

但如果是历史版本,你可以把代码包装进 @variants responsive { ... }

@layer utilities {
  @variants responsive {
    .-z-1 {
      z-index: -1;
    }
  }
}

我们可以使用 md:-z-1 lg:z-0 来响应式地根据屏幕尺寸进行设置。

🔥 多个 v-model

Vue3 中不限制 v-model 数量:

<AddressForm
  v-model:street-name="streetName"
  v-model:street-number="streetNumber"
  v-model:postal-code="postalCode"
  v-model:province="province"
  v-model:country="country"
/>

可以更容易地处理复杂的表格!

首先,我们需要创建一个 props 和 处理 v-model 的事件(这里简化了 v-model 的数量):

<!-- AddressForm.vue -->
<script setup>
  // Set up all the props
  defineProps({
    streetName: {
      type: String,
      required: true,
    },
    streetNumber: {
      type: Number,
      required: true,
    },
    // ...
    country: {
      type: String,
      required: true,
    },
  });

  // Set up our events
  defineEmits([
    "update:streetName",
    "update:streetNumber",
    // ...
    "update:country",
  ]);
</script>

在组件内部使用 prop 读取值,使用 update:<propname> 来触发更新:

<template>
  <form>
    <input
      type="text"
      :value="streetName"
      @input="$emit('update:streetName', $event.target.value)"
    />
    <input
      type="text"
      :value="streetNumber"
      @input="$emit('update:streetNumber', $event.target.value)"
    />
    <!-- ... -->
    <input
      type="text"
      :value="country"
      @input="$emit('update:country', $event.target.value)"
    />
  </form>
</template>

你可以在官方文档中阅读多个 v-model 的 更多信息

🐦 本周发推内容

https://twitter.com/MichaelThiessen/status/1578412323617865728?s=20&t=a7kv-3xVs0L_ZP1MoC_-wQ

📜 关于 Suspense 你需要的知道的一切

我在 VueSchool.io 写了这篇文章,用来解释关于这个概念的误解。

如果你需要在应用中载入数据,Suspense 会很有用。

这里有些示例,你可以一边阅读一边编写代码!

点击阅读: 关于 Suspense 你需要的知道的一切

💬 代码注释

“好的代码本身就是最好的文档。如果你需要添加代码注释,应当问问自己,‘我可以怎样改进代码,就可以不需要编写注释了?’” —Steve McConnell

🧠 间隔重复:扁平化 Nuxt Content 路由

想要长时间牢牢记住某些事情,最好方式就是定期回顾,逐渐增加回顾的间隔 👨‍🔬

实际上,记住这些 tips 比发呆有用得多,这是几周前的一个 tip 可以唤起你的记忆。

我想把我的博客内容组织成几个文件夹:

  • 文章:content/articles/
  • Newsletters:content/newsletters/

默认情况下,Nuxt Content 会将这些路由设置为包括这些前缀。但我希望我所有的路由都是在根级别:

我们可以通过覆盖 _path 属性,为每个 Markdown 文件手动做到这一点,通过设置 frontmatter:

---
title: My Latest Article
date: today
_path: "/my-latest-article"
---

这是很繁琐的,容易出错的,而且一般来说很烦人。

幸运的是,我们可以写一个简单的 Nitro 插件,自动完成这一转换。

server/plugins/ 创建一个 content.ts 文件:

export default defineNitroPlugin((nitroApp) => {
  nitroApp.hooks.hook("content:file:afterParse", (file) => {
    for (const prefix of ["/articles", "/newsletters"]) {
      if (file._path.startsWith(prefix)) {
        // Keep the prefix so we can query based on it still
        file._original_dir = prefix;
        // Remove prefix from path
        file._path = file._path.replace(prefix, "");
      }
    }
  });
});

Nitro 是 Nuxt 内部使用的服务器。我们可以进入处理过程,做一些调整。

如果我们根据路径进行过滤,这样做会破坏 queryContent 的调用,因为queryContent 正在查看我们刚刚修改的 _path 属性。这就是为什么我们要保留那个原始目录。

我们可以修改我们的 queryContent 调用来过滤这个新的 _original_dir 属性。

// Before
queryContent("/articles");

// After
queryContent().where({
  _original_dir: { $eq: "/articles" },
});

提示:使用 nuxi clean 来强制 Nuxt Content 重新获取并重新转换你的所有内容。

p.s. I also have three courses: Vue Tips Collection, Reusable Components and Clean Components

来源

原文 https://michaelnthiessen.com/weekly-082-october-12/

本作品采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。