前沿
事情是这样的,在 react 中,我们通常使用 && 这种判断方式来达到 vue 中的 v-if 的效果,表示某一段 dom 元素到底在某些条件下到底要不要展示的问题
比如在 vue 中,你可以这样写,这段代码中 div 由于 v-if 取决于 visible 的值,通常是一个布尔值,但是即便是你把 visible 给成数字 0,这个 div 也是不展示的,所以你也可以用 v-if 判断 list.length,表示 list 的长度为 0 的时候不展示相关的 dom
<template>
<div v-if="visible"></div
</template>
但是在 react 中,我们通常使用 && 来进行判断,如果条件成立,就渲染 && 后面的 dom 元素,这段代码中 h1 标签的展示取决于 visible
export default function App() {
return (
<div>
{visible && <h1>Hello StackBlitz!</h1>}
<p>Start editing to see some magic happen :)</p>
</div>
);
}
但是如果用 0 来判断的话就会出现异常
这样我在写这种代码的时候很容易出现问题,因为这样会在页面上显示一个 0
{list.length && <h1>Hello StackBlitz!</h1>}
原因
那为什么在 vue 中就可以呢?我们看一下 vue 中通过 v-if 最终会把代码编译成什么形式。按照刚才的例子,vue 的编译结果如下
render(_ctx, _cache, $props, $setup, $data, $options) {
return visible ? (_openBlock(), _createBlock("div", { key: 0 }))
: _createCommentVNode("v-if", true)
}
本质是一个三元运算符,所以会进行隐式类型转换,当 visible 是 true 的时候会进行 div 的创建,如果是 false,会在当前模版中创建一个注释节点(也可称为占位节点),长这样
react 中虽然是 jsx 的语法,但本质还是 js 基础的那一套,所以在开发的过程中,没有 vue 的模版语法,那要了解为什么 0 && 会出现问题,还得了解 && 的本质
&& 的本质
既然要提到 && 的本质,那说明这个问题并不是 react 的问题,对于 && 在 MDN 上的解释是
一般来说,当从左到右求值时,该操作符返回第一个假值操作数的值;如果它们都是真值,则返回最后一个操作数的值
其本质也就是从左到右对整个操作进行求值,遇到第一个假值就会立即返回,如果所有的操作都是真值,则返回最后一个操作值
同时我们要知道转换成 false 的有以下内容:
false/null/NaN/0/空字符串/undefined
所以这个时候,问题来了,虽然会进行隐式类型转换,但是 && 运算符会保留所有非布尔值并原样返回它们
"" && 1 // ''
0 && 1 // 0
NaN && 1 // NaN
所以你知道了当你在 react 中使用 && 的时候,当然不仅仅是 react,它会返回0
同样的对于 NaN 来说,他也会在页面上显示 NaN,一定要注意
如何解决
那这种情况怎么解决呢?
- 使用 !!
我们可以使用 !! 来将 0 转换成布尔类型
!!list.length && <Component list={list} />
- 修改判断条件,不依赖隐式类型转换
list.length >= 1 && <Component list={list} />
- 使用三元表达式,修改返回结果
list.length ? <Component list={list} /> : null
- 使用判断条件
if(list.length){return <Component list={list} />}
- Boolean 类型转换
Boolean(list.length) && <Component list={list} />
平时在用的时候,使用上述的方式最好对 && 操作符左侧的内容进行转换,得到想要的结果,而不是出现不可预料的问题