Skip to content

🔥 (#70) Configuration driven templates

July 2022

Heyo!

我们在盛夏了。

我要在我的 2015 款 MBP 烧伤我的腿之前写完周刊。

但比起阳光和空气是值得的。

靠着空调,我才能在如此潮湿炎热的晚上睡觉。

我的空调已经超过 30 年历史了,看起来还能再使用 25 年。

空调运行起来噪声很大,但年复一年还能继续使用。

哈哈,我知道你并不关心我的空调。

接下来开始周刊内容。

—Michael

🔥 Ref vs. Reactive

在使用 composition API 的时候,用 ref 好还是 reactive 更好?

这里列举一些 refreactive 有优势的地方。

使用 ref 包裹 js 对象,同时对比 reactive 和普通对象的使用场景,区别显而易见:

// I can expect this ref to update reactively
if (burger.value.lettuce) {
  // ...
}

// I have no clue if this value is reactive
if (burger.lettuce) {
  // ...
}

使用 watch 方法时,ref 会自动解构,非常易用:

// Ref
const refBurger = ref({ lettuce: true });
watch(
  // Not much, but it's a bit simpler to work with
  refBurger,
  () => console.log("The burger has changed"),
  { deep: true }
);

// Reactive
const reactiveBurger = reactive({ lettuce: true });
watch(
  () => burger,
  () => console.log("The burger has changed"),
  { deep: true }
);

使用 ref 还有一个优点,你可以在 ref 中放入 reactive 对象。这样可以任意组合 reactive 对象,底层还是使用 ref

const lettuce = ref(true);
const burger = reactive({
  // 把 ref 变成属性
  lettuce,
});

// 直接监听 reactive 对象
watchEffect(() => console.log(burger.lettuce));

// 也可以直接监听 ref
watch(lettuce, () => console.log("lettuce has changed"));

setTimeout(() => {
  // 更新 ref 的值,会自动触发所有的 watchers
  lettuce.value = false;
}, 500);

🔥 配置驱动模板

我简化模板的一个常用方式是配置驱动

我不会像这样重复编写模板:

<template>
  <div>
    <menuitem @click="openContact"> Open Contact </menuitem>
    <menuitem @click="createContact"> Create Contact </menuitem>
    <menuitem @click="sendEmail"> Send Email </menuitem>
    <menuitem @click="resetSystem" danger> Reset </menuitem>
  </div>
</template>

通常会重构成通过配置项来驱动渲染:

<template>
  <div>
    <menuitem
      v-for="item in menuItems"
      :key="item.text"
      :danger="item.danger"
      @click="item.action"
    >
      {{ item.text }}
    </menuitem>
  </div>
</template>
<script setup>
  const openContact = () => {
    /* ... */
  };
  const createContact = () => {
    /* ... */
  };
  const sendEmail = () => {
    /* ... */
  };
  const resetSystem = () => {
    /* ... */
  };

  const menuItems = [
    {
      text: "Open Contact",
      action: openContact,
    },
    {
      text: "Create Contact",
      action: createContact,
    },
    {
      text: "Send Email",
      action: sendEmail,
    },
    {
      text: "Reset System",
      action: resetSystem,
      danger: true,
    },
  ];
</script>

我们没有减少代码,但让代码更简洁了:

  • 配置项更易读 — 阅读代码很复杂,因为你要搞清楚具体的逻辑,但配置项是非常简单易懂的。
  • 更少的逻辑意味着更少的 bug — 上面的配置项是一个简单的对象数组,所以 bug 通常不会在数组里出现。
  • 动态组件会更灵活 — 我们让菜单组件动态渲染,获得了更多灵活性。

关于这个观点,我写了这篇文章

📜 编写自己的 Vue.js

一个大家都感同身受的权衡问题,是使用现成的解决方案,还是自己重新实现一个方案?

我写了一个自己的 Vue.js

💬 混沌

“自动化的混乱会让混乱更快发生。” — Mark Fewster

🧠 间隔重复:循环的目的是什么?

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

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

我常常忘记这些,这个 tip 对我很有用。真希望我不需要持续回顾了。

js 中有三种 for 循环类型:

  1. for...in
  2. for...of
  3. for

你知道该使用哪一种吗?

如果要遍历对象的属性,可以使用 for...in

const numbers = {
  one: 1,
  two: 2,
  three: 3,
};

// 获得对象的属性,而不是值
for (const number in numbers) {
  console.log(number);
}

// Prints: 'one' 'two' 'three'

列表 list中,或者说可迭代对象,比如数组、set 集合,可以使用 for...of

const numbers = ["one", "two", "three"];

// 得到数组的每一项
for (const number of numbers) {
  console.log(number);
}

// Prints: 'one' 'two' 'three'

也可以使用 for...in 来处理数组,因为数组的索引都是对象的属性。但得到的顺序可能不对,也会得到数组拥有的其他属性。

常规使用 for 循环,可以对循环时候拥有更多控制权。

p.s. I also have two courses: Reusable Components and Clean Components

来源

https://michaelnthiessen.com/weekly-070-july-20/