我想在我的一个项目中实现一个通知消息,类似于您在 Google Docs 中保存文档时看到的。换句话说,每次进行更改时,都会显示一条消息,指示文档正在保存。然后,一旦更改保存,消息将变为:“所有更改已保存在云端硬盘中。”
让我们看看如何使用布尔值来实现这一点,但实际上涵盖了三种可能的状态。这绝对不是唯一的方法,坦率地说,我甚至不确定这是否是最佳方法。无论如何,它对我有用。
这是一个“正在保存...”状态的示例

...以及“已保存”状态

使用Boolean
值来定义状态是我的第一反应。我可以有一个名为isSaving
的变量,并使用它在我的模板中呈现条件字符串,如下所示
let isSaving;
...以及在模板中
<span>{{ isSaving ? ‘Saving...’ : ‘All changes saved’ }}</span>
现在,每当我们开始保存时,我们将值设置为true
,然后在没有保存正在进行时将其设置为false
。很简单,对吧?
但是,这里存在一个问题,它有点用户体验问题。默认消息呈现为“所有更改已保存”。当用户最初访问页面时,没有进行保存,即使从未发生过保存,我们也会收到“已保存”消息。我更希望在第一次更改触发第一个“正在保存”消息之前不显示任何内容。
这需要在我们的变量isSaving
中添加第三种状态。现在问题变成了:我们将值更改为字符串变量作为三种状态之一吗?我们可以这样做,但是如果我们可以在当前布尔变量本身中获得第三种状态怎么办?
isSaving
可以取两个值:true
或false
。但在我们声明语句let isSaving;
之后,直接的值是什么?它是undefined
,因为任何变量的值在声明时都是undefined
,除非为其分配了某个值。太好了!我们可以利用该初始undefined
值来发挥我们的优势……但是,这需要我们稍微更改一下在模板中编写条件的方式。
我们正在使用的三元运算符对于任何无法转换为true
的内容都计算为第二个表达式。undefined
和false
的值都不是true
,因此对于三元运算符而言,它们都解析为false
。即使是if/else语句也会以类似的方式工作,因为else
针对任何不是true
的内容进行评估。但我们希望区分undefined
和false
。这可以通过显式检查false
值来修复,如下所示
<span>
{{ isSaving === true ?
‘Saving...’ :
(isSaving === false ? ‘All changes saved’: ‘’)
}}
</span>
我们现在正在严格检查true
和false
值。这使得我们的三元运算符稍微嵌套了一些,难以阅读。如果我们的模板支持if/else语句,那么我们可以像这样重构模板
<span>
{% if isSaving === true %}
Saving...
{% elseif isSaving === false %}
All changes saved
{% endif %}
</span>
啊哈!当变量既不是true
也不是false
时,不会呈现任何内容——这正是我们想要的!
这意味着您还可以使用
null
、0
、""
、'asdf'
或除true
和false
之外的任何内容来指示状态。在某些情况下,我更喜欢存储在命名常量中的数值,以提高可读性来指示自定义状态。我认为最好只使用3种状态,并将它们存储为字符串或整数。
1 – 已加载
2 – 未保存
3 – 已保存
对我来说,在处理像这样的异步交互时,我会使用一个名为saveState的状态变量,它可以是以下任何值:'IDLE'、'LOADING'、'SUCCESS'、'FAIL'。这样你就可以处理失败的请求
我同意这一点而不是文章。undefined 应该与未定义的语义一起使用。如果将其用于其他目的,将会造成混淆。
是的~有时它效果很好,我想将'undefined'与'缺失状态'进行比较,没有'isSaving',也没有“正在保存...”状态的描述
我不建议依赖未初始化的变量;
它使代码更难以理解。
您必须在每次更改其周围的代码时考虑该变量,从而增加了系统的摩擦。
类型分析和检查可能会感到困惑。
与前一点相关;关于提升的运行时/编译器中的一个小错误将产生不同的行为。
但最重要的是,这表明您可能缺少某些内容,这些内容会减少耦合并提高可测试性。例如,我希望找到某种要保存的更改队列或存储库,我可以查询未完成的操作。
我建议将三种布尔状态重命名为True、False和Cat。我相信这样的命名很快就会流行起来。
习惯了之后,阅读起来会更容易一些
{{
isSaving === true
? ‘Saving…’
isSaving === false
? ‘All changes saved’
: ‘’
}}
这里给出的示例很糟糕。有一些抽象模型表示值的存在或不存在。一些 JS 实现:https://gcanti.github.io/fp-ts/modules/Option.ts.html https://folktale.origamitower.com/api/v2.3.0/en/folktale.maybe.html https://funfix.org/api/core/classes/option.html
这很糟糕,如果我在正在处理的项目中找到此代码,我会立即对其进行重构(在尝试理解到底发生了什么事之后)。首先,布尔变量不应这样使用,这会让其他阅读代码的人感到困惑,并且从字面上来说是一种技巧。其次,嵌套三元运算符也是非常混乱的代码,恕我直言
三元运算符不必难看。这只是一个格式问题。例如在 JSX 中
请注意,PHP 对三元运算符链的支持不太好。
此实现有其局限性。如果保存失败,我想更新状态消息以传达它。
我更喜欢在这里使用更多定义的状态常量。
是的,我同意其他帖子的观点,这是一种反模式。尝试赋予
undefined
额外的含义为细微错误的潜入创造了空间。它在您的代码中创建了隐式知识,即undefined
实际上意味着“初始状态”,而不是“我忘记设置此变量”。使用字符串使变量具有一致的类型,这使得类型检查更容易,并且使变量的值更直接地清楚地表明它代表什么,尤其是在将其传递给其他函数或存储在使用位置之外的情况下。我可能会将字符串提取到一个常量中这样,您完全避免了条件逻辑,并且可以轻松地添加新的状态,例如
error
。