没时间学 Vue (7) —— 渲染(二):条件渲染 v-if

本文详细介绍了Vue.js中的条件渲染指令,包括v-if、v-else、v-else-if的使用,并通过实例展示了它们的区别和潜在问题。文章探讨了v-if与v-for混用的渲染结果和性能问题,以及v-show的原理。最后提出了几个涉及条件渲染的编程挑战,鼓励读者实践并思考解决方案。

上一篇说了列表渲染 v-for,本篇继续讲渲染中的 条件渲染 v-if 。

Vue 官方的说明在:https://cn.vuejs.org/v2/guide/conditional.html

 

1、v-if 


条件渲染,顾名思义,就是 “在某种条件下才渲染” 以及 “在其他条件下不渲染” —— 典型的 if-else 场景。

比如说,登录到某个系统的时候,可以按照 “账户 + 密码” 的方式登录,也可以按照 “电话号码 + 验证码” 的方式的登录。

简易版的画面效果,大概是这样的:(没用 CSS 所以长得比较抱歉)

                         

这个画面中的组件数量就稍微多了一些起来,需要把好几个组件合并成一个大组件来处理。

为了更好地聚焦在条件渲染上,我们把上面的画面进一步简化,只保留一个组件。类似这样的:

                            

我们还是先来看一下其他的模板渲染引擎里是怎么写的。

JSP 的话,可能是这样的:

<c:if test="${loginMode == 1}">
   <div>账号:<input type="text"></div>
</c:if>
<c:if test="${loginMode == 2}">
   <div>手机:<input type="text"></div>
</c:if>

Thymeleaf 的话,可能是这样的:

<div th:if="${loginMode == 'byAccount'}">
    <div>账号:<input type="text"></div>
</div>
<div th:if="${loginMode == 'byTelephone'}">
    <div>手机:<input type="text"></div>
</div>

Vue 里面也差不多,大概是这样的:(看起来跟 Thymeleaf 基本是一样的)

<div v-if="loginMode === 'byAccount'">
    <div>账号:<input type="text"></div>
</div>
<div v-if="loginMode === 'byTelephone'">
    <div>手机:<input type="text"></div>
</div>

 

2、v-else、v-else-if


上面的例子中,我们连续使用了 2 个 v-if 。相当于是写了这样一段代码:

if (loginMode == "byAccount") {

    显示账号组件;

}

if (loginMode == "byTelephone") {

    显示手机组件

}

看起来有什么问题不? —— 是的,没什么问题 (的样子)。

那咱们就 “制造” 一个问题出来吧,你见过只有 if 语句的开发语言不 —— 或者说,你写代码的时候只用 if 语句做条件判断?

正常的开发语言,都有 if ... else 、if ... else if ... 这样的条件语句,大部分也有 switch ... case 这样的处理更多条件的 “威力加强版” 条件语句,

更不用提还有在 case 语句中可以指定表达式的 (比如说 JavaScript)。

Vue 中也提供类似的了 v-else 和 v-else-if 条件渲染指令

纯粹为了演示这两条指令的用法的话,可以把上面的代码改成这样的:

v-else 版本:

      <div v-else>
        <div>手机:<input type="text" :value="telephone"><input type="button" value="发送验证码"></div>
        <div>验证码:<input type="text" :value="verificationCode"></div>
      </div>

v-else-if 版本:

      <div v-else-if="loginMethod === 'byTelephone'">
        <div>手机:<input type="text" :value="telephone"><input type="button" value="发送验证码"></div>
        <div>验证码:<input type="text" :value="verificationCode"></div>
      </div>

上面 3 种写法 (v-if + v-if、v-if + v-else、v-if + v-else-if) 在画面效果来看,都完全一样。

但是,还是希望你稍微停下来,认真思考一下,各自有什么样的潜在问题 —— 虽然都是抓住了老鼠的猫,但是还是有些细小差别的。

当然,上面的场景只是纯粹为了展示各种语法、有些牵强,我们会在文末的思考题中模拟更为真实的场景 😀

重要的事情差点儿忘说了 ......

1)Vue 不支持 switch ... case 这类条件渲染的。

目前来说,你还只能堆 v-if 、v-else-if 、v-else 语句,稍微麻烦一点儿、但是也绝对够用。

将来使用动态组件的时候,能做得更优雅一些 —— 当然,也会指数级地更烧脑子、更费时间。

2)尽量不要嵌套、或者少嵌套条件渲染语句。

这个倒不是 Vue 不支持,主要是我们的眼睛不支持,看上去会晕的。

其实不止 Vue,其他开发语言的嵌套多了,也是会晕的 —— 所以,各种编码规约上,也会建议控制嵌套处理的深度。

 

3、v-if 和 v-for 的混合使用


Vue 官方的 “条件渲染” 和 “列表渲染” 文档中,都建议不要在同一个元素上同时使用 v-if 和 v-for

https://cn.vuejs.org/v2/guide/conditional.html#v-if-%E4%B8%8E-v-for-%E4%B8%80%E8%B5%B7%E4%BD%BF%E7%94%A8

https://cn.vuejs.org/v2/guide/list.html#v-for-%E4%B8%8E-v-if-%E4%B8%80%E5%90%8C%E4%BD%BF%E7%94%A8

看上去非常费解,反正我第一眼是没太看明白的 —— 当年学 C 语言的时候,遇到 ++++i---- 这类考优先级的问题也是直接投降。

工作之后,也会尽可能绕开这类写法,或者是使用括号等把复杂表达式拆成更简单、更易懂的方式。

以我当前的认知来看,v-if 和 v-for 在大部分情况下一起使用是没有大问题的 —— 少数出问题的时候,也很容易改正。

下面我们就来具体拆解一下,可能的问题有哪些。

1)v-for + v-if / v-else / v-else-if 的渲染结果问题:

我们还是使用具体的场景来描述这个问题。

比如说,有人给了我们这些数字:3, 5, 6, 8, 7, 4,并且要我们显示其中的偶数。

我们大概可以这么来做:

    <div id="app">
      <div v-for="number in numbers" v-if="number % 2 == 0">{{number}}</div>
    </div>
    <script>
      var app = new Vue({
        el: "#app",
        data: {
          numbers: [3, 5, 6, 8, 7, 4]
        },
      });
    </script>

结果也是正确的 —— 注意,我们在 div 上同时使用了 v-for 和 v-i,但是结果仍然是正确的。

正当我们要宣告胜利的时候,需求发生了变化 —— 实际项目中也是一样,想要需求不发生变化,比要求海上不起风浪还要难。

还是上面的那些数字,但是输出其中 ≥ 10 的数字。

于是我们把上面的代码中的 v-if 稍微改了一下,改成了 ,瞬间搞定 —— 小 CASE。

然后需求又变了。我们改完后页面上什么都没有显示,不明就里的吃瓜群众还以为程序 Bug 了;所以呢,没有匹配条件的数据的时候,画面要显示 “没有匹配的数据” 这几个字。

不就是个 v-else 语句嘛,简单!所以我们又加了一行。

等我们查看画面显示的时候,瞬间惊呆 —— 

这个就是所谓的 v-for 和 v-if 的优先级的问题

虽然我们把 v-for 和 v-if 写到了一起,实际跟下面的代码的效果是一样的:

所以,画面上给我们显示了 N 多条 “没有匹配的数据”。

那要怎样才能实现想要的效果呢?方法有很多种,留到思考题再说 😄😄😄

2)v-for + v-if 的渲染性能问题:

这个其实在 Vue 官网上不是很醒目的专栏【风格指南】中提到了。

https://cn.vuejs.org/v2/style-guide/#%E9%81%BF%E5%85%8D-v-if-%E5%92%8C-v-for-%E7%94%A8%E5%9C%A8%E4%B8%80%E8%B5%B7%E5%BF%85%E8%A6%81

准确来说,Vue 官方是强烈反对在同一个元素上混用 v-for 和 v-if 的。

点开其中【详解】的说明,能看到下面这段没有加亮但是其实很关键的描述 —— 潜在的性能问题。

大部分情况下其实遇不到这个问题 —— 尤其是前端自身的处理逻辑很简单、数据也不多,而且不需要自己保存大量临时数据的时候(复杂的菜单或者权限设置之类)。

【详解】中也推荐使用 “计算属性” 这个我们还没讲到的知识点来解决性能问题。计算属性还是比较常用 ,先种个草。

 

不过,既然 Vue 官方极力反对(推荐等级是“必要的”),虽然问题不大,咱们也尽量不要混用 v-for 和 v-if

 

4、v-show


如果你有过开发 GUI 应用的经验的话,可以回顾一下 GUI 组件里面的 “可见状态” 的概念。

组件有了,但是 “不可见” ,所以画面上你看不到,也操作不了。

HTML 中各个组件也有类似的 “可见状态” 的控制方式,但是不是 HTML 的属性,而是 CSS (样式)属性。

更要命的是,有 visibility 和 display 两个之多;除了可见不可见之外,还能控制布局方式(又要开始分裂了 ......)

有时间的话,可以通过下面的文章速成一下: https://www.html.cn/qa/css3/15704.html

没时间的话,只要记住下面这些平常无奇、但是非常基础的原则。

如果我们想要把某个组件从画面上抹去,有这么两种做法:

1)压根儿就不创建这个组件,如果创建了的话就删掉 —— 这个就是 v-if

  (删除的描述不完全正确,Vue 做了很多优化和复用的事情,不过我们可以简单理解成删除)

2)虽然创建了,但是设置成 “不可见” 的 —— 这个就是我们接下来要说的 v-show。

 

我们用 v-show 的方式来重新实现 v-if 章节的需求:   有人给了我们这些数字:3, 5, 6, 8, 7, 4,并且要我们显示其中的偶数。

代码大概是这样的:(为了便于理解,我们同时列出了 v-if 版的代码)

    

画面上看起来的效果也是一样的,但是生成的 HTML 组件给我们揭示 v-show 和 v-if 的本质差别。

                               

由于上面的差异,在非常追求性能的时候,还是需要区别对待的 —— 大部分的情况下,可能升级一下 CPU 和内存更加有效。

具体可以看 Vue 的官网说明: https://cn.vuejs.org/v2/guide/conditional.html#v-if-vs-v-show

 

5、key 和组件复用


Vue 官网上还提到了 —— 也是出于性能的考虑(复用 HTML 组件)。

不过在【风格指南】中,这条甚至都够不上 “推荐” 的级别,咱们先跳过去,有时间再慢慢说。

https://cn.vuejs.org/v2/style-guide/#%E6%B2%A1%E6%9C%89%E5%9C%A8-v-if-v-else-if-v-else-%E4%B8%AD%E4%BD%BF%E7%94%A8-key-%E8%B0%A8%E6%85%8E%E4%BD%BF%E7%94%A8

对了,v-for 里面是 "必须" 设置各个元素的 key 的 —— 正规开发中静态检查会报 Warning 的。

https://cn.vuejs.org/v2/style-guide/#%E4%B8%BA-v-for-%E8%AE%BE%E7%BD%AE%E9%94%AE%E5%80%BC%E5%BF%85%E8%A6%81

这个要求除了有性能方面的考虑,还有过渡动画方面的原因。

说起来更加话长,先记住这条规定就行;记不住问题也不大,正规开发时会给你 Warning 的 😁

 

6、思考题


学了条件渲染,就能在前端做出各种各样不同的效果了 —— 当然,现在还不能对样式有过高要求。

今天的思考题也比较难,需要综合使用之前学到的各种知识。

1)给定一组数字:3, 5, 6, 8, 7, 4,实现以下效果。

                    

友情提示:

1)可以为每一种 “检索方式” 准备一组用于显示的组件,用 v-if 控制显示哪一组。

 

2)在上面的基础上,追加以下效果。

友情提示:

1)用一个函数来计算 ≥ 10 的所有数字的数组(回忆一下之前提到的函数的写法)。

     要用到 Array.filter() 函数:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/filter

2)把上面的函数用到 v-if 和 v-for 语句中。

     比如说: 

3)如果你已经学过了 “计算属性”,也可以使用计算属性来做。

     https://cn.vuejs.org/v2/guide/computed.html

 

3)在上面的基础上,把各种 “检索条件” 的 v-if 代码合并成一套。

友情提示:

1)用一个函数来计算当前选中检索条件下、匹配的数字的数组;

2)其余的基于 2)中的函数使用方式来修改;

3)合并完成后比对一下合并前后的代码,看看能有什么新的发现。优雅?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值