Appearance
🔥 (#70) Configuration driven templates
July 2022
Heyo!
我们在盛夏了。
我要在我的 2015 款 MBP 烧伤我的腿之前写完周刊。
但比起阳光和空气是值得的。
靠着空调,我才能在如此潮湿炎热的晚上睡觉。
我的空调已经超过 30 年历史了,看起来还能再使用 25 年。
空调运行起来噪声很大,但年复一年还能继续使用。
哈哈,我知道你并不关心我的空调。
接下来开始周刊内容。
—Michael
🔥 Ref vs. Reactive
在使用 composition API 的时候,用 ref 好还是 reactive 更好?
这里列举一些 ref 比 reactive 有优势的地方。
使用 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
一个大家都感同身受的权衡问题,是使用现成的解决方案,还是自己重新实现一个方案?
💬 混沌
“自动化的混乱会让混乱更快发生。” — Mark Fewster
🧠 间隔重复:循环的目的是什么?
想要长时间牢牢记住某些事情,最好方式就是定期回顾,逐渐增加回顾的间隔 👨🔬
实际上,记住这些 tips 比发呆有用得多,这是几周前的一个 tip 可以唤起你的记忆。
我常常忘记这些,这个 tip 对我很有用。真希望我不需要持续回顾了。
js 中有三种 for 循环类型:
for...infor...offor
你知道该使用哪一种吗?
如果要遍历对象的属性,可以使用 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