Skip to content

🔥 (#78) Prose Components with Nuxt Content

September 2022

Hey all,

I hope you're having a lovely week!

Recently I've been reading through Wheel of Time again. At this pace, it may take me a couple years to finish though...

Of course, I've also been working on Mastering Nuxt 3, as well as some tips and articles for you.

Enjoy!

—Michael

🔥 Force Vue to Re-Render Correctly

If you find yourself needing to force Vue to re-render a component, chances are the reactivity in your app is broken somewhere.

But, if you have a valid use case, forceUpdate is not working, or you simply need to get things working quickly, the best way to do this is through the Key Changing Technique:

<template>
  <MyComponent :key="componentKey" />
</template>
import { ref } from "vue";
const componentKey = ref(0);

const changeKey = () => {
  componentKey.value += 1;
};

Here’s how you’d do it with the Options API if you’re not using Vue 3 or the Composition API:

export default {
  data() {
    return {
      componentKey: 0,
    };
  },
  methods: {
    changeKey() {
      this.componentKey += 1;
    },
  },
};

Using the key attribute lets us give Vue more information so it can correctly remove and replace DOM elements on the page. Because of the reactivity system, Vue can get confused about which elements need to be replaced in the DOM and which need to stay.

When we change the value of our key, Vue knows that this is a “new” component. It will destroy the existing component and then create and mount an entirely new one.

Problem solved!

But before you reach for this solution, make sure that there isn’t a reactivity issue in your application. This should only be used as a last resort, and is not a recommended approach.

🔥 Prose Components in Nuxt 3

With Nuxt Content 2 we can customize how Markdown gets rendered in our Nuxt 3 apps by creating our own custom Prose components.

We do get code highlighting built-in through Shiki, but I already have a custom theme for Prism.

So I needed to create a custom ProseCode component that used PrismJS to render the code blocks from my Markdown:

<template>
  <pre :class="`language-${language}`"><code v-html="highlighted"></code></pre>
</template>
import Prism from 'prismjs';

const props = withDefaults(
  defineProps<{
    code?: string;
    language?: string | null;
    filename?: string | null;
    highlights?: Array<number>;
  }>(),
  {
    code: '',
    language: null,
    filename: null,
    highlights: [],
  }
);

const highlighted = props.language
  ? Prism.highlight(
      props.code,
      Prism.languages[props.language],
      props.language
    )
  : props.code;

When we place this component in ~components/content and name it ProseCode, Nuxt Content knows to use it when rendering code blocks from Markdown.

We get a few props, and then use PrismJS to highlight it. This is all done on the server too, so our code is already highlighted before it hits the client.

Note: the formatting inside of the pre tag looks weird because it will preserve any formatting, including newlines. Moving the code element to the next line and indenting would cause the code rendered to the page to also have an extra newline and a few spaces in front of it.

You can create custom Prose components for most elements.

📜 Stop Writing Dirty Components

Getting our code to work is great (and obviously necessary).

But as professionals, we know that getting code to “work” is only 10% of the job. It also needs to work well.

This is why we can't write Dirty Components, but instead need to write Clean Components.

Read it here: Stop Writing Dirty Components

📜 Coding Better Composables: Flexible Arguments (2/5)

I teamed up with Vue Mastery to create this series on coding better composables.

In this series we cover five different patterns.

For each, we show how you can implement it and then we see it in action with a composable from VueUse.

This second article is on using ref and unref to make the arguments more flexible.

Read it here: Coding Better Composables: Flexible Arguments (2/5)

💬 Mass producing software

"You can mass-produce hardware; you cannot mass-produce software; you cannot mass-produce the human mind." —Michio Kaku

🧠 Spaced-repetition: Nuxt Content Queries

The best way to commit something to long-term memory is to periodically review it, gradually increasing the time between reviews 👨‍🔬

Actually remembering these tips is much more useful than just a quick distraction, so here's a tip from a couple weeks ago to jog your memory.

Nuxt Content 2 gives us an effortless way to query our content using the queryContent method:

// composables/useArticles.js

export default () =>
  queryContent("articles")
    .where({
      // Optional fields that may be true or non-existent
      ghost: { $ne: true },
      newsletter: { $ne: true },
      // Don't render articles scheduled for the future
      date: { $lte: new Date() },
    })
    .only(["title", "path", "description", "date", "tags"])
    .sort({ date: -1 })
    .find();

Here, I’ve created a composable called useArticles for my blog, which grabs all of the content inside of the content/articles/ directory.

The queryContent composable is a query builder, which gives us a lot of expressiveness in what data we fetch. Let’s see how we’re using this here.

First, we’re using a where clause to filter out all the articles we don’t want. Sometimes I will add an article before I want it to be “published” to the site.

I do this by setting the date in the future and then only taking articles before “today” using this clause:

date: {
  $lte: new Date();
}

Second, some articles are the newsletters I write each week. Others are pieces of content that I want to keep in the articles folder but don’t want to be published.

I use frontmatter fields to specify this:

---
newsletter: true  # This is a newsletter
---
---
ghost: true  # This content won't appear on the site
---

Third, we use the only clause to grab just the fields we need. By default, the queryContent method returns a lot of data, including the entire piece of content itself, so this can make a big difference in payload size.

Lastly, as you have probably guessed, we have a sort clause to sort the articles so the most recent ones appear last.

The queryContent composable has more options than this, which you can read about on the docs.

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

来源

原文 https://michaelnthiessen.com/weekly-078-september-14/

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