vue.js实现条件渲染的实例代码


Posted in Javascript onJune 22, 2017

一、初探条件渲染

vue 的条件渲染,仍旧依赖于指令系统,下面逐个介绍:

(1)v-if

<div id="app">
  <div v-if="c1">c1</div>
</div>
......
var app = new Vue({
  el: '#app',
  data: {
    c1: false
  }
});

当 c1 为真值的时候,渲染出 v-if 所绑定的元素,否则不渲染出该元素。渲染结果如下:

<div id="app"></div>

(2)v-else

<div id="app">
  <div v-if="c1">c1</div>
  <div v-else>c1 is not true</div>
</div>
......
var app = new Vue({
  el: '#app',
  data: {
    c1: false
  }
});

当 c1 为真值的时候,渲染 v-if 所绑定的元素,否则渲染 v-else 所绑定的元素。这里值得注意的是,在 Handlebars 模板引擎里面,else 可以和 each 所搭配,当遍历次数为0的时候,则渲染 else 块所对应的内容;而对于 vue,官方给出的说法是,每个 v-else 所绑定语句必须绑定在 v-if 或者 v-else-if 语句的后面。一开始我还抱有一丝希望地去试了一下,结果。。。

vue.js实现条件渲染的实例代码

遍历次数为0的时候,v-else 绑定的元素没有渲染出来,而且控制台还报错了。

个人感觉,在这一方面,vue 的模板引擎可能有所欠缺。虽然说,我们可以利用在循环中添加条件判断实现相同的功能,但却需要添加额外的代码。

(3)v-else-if

<div id="app">
  <div v-if="c1">c1</div>
  <div v-else-if="c2">c2</div>
</div>
......
var app = new Vue({
  el: '#app',
  data: {
    c1: false,
    c2: true
  }
});

这里先检查 c1 是否为真值,是则渲染出 v-if 绑定的元素,否则检查 c2 是否为真值,是则渲染出 v-else-if 所绑定的元素。如果 c1 / c2 都不为真值,则都不渲染。渲染结果如下:

<div id="app">
  <div>c2</div>
</div>

不难理解,v-if、 v-else、 v-else-if 跟类 C 语言中的 if、else、else if 功能相仿。

二、条件渲染优化

除了提供跟类 C 语言中的 if、else、else if 相似的功能以外,vue 还为开发者提供了性能优化方案。

(1)v-show

v-show 有着和 v-if 相似而又不同的功能,v-if 依赖于控制 DOM 节点,而 v-show 是依赖于控制 DOM 节点的 display 属性。

<div id="app">
  <div v-show="c4">c4</div>
</div>
......
var app = new Vue({
  el: '#app',
  data: {
    c4: false
  }
});

当 v-show 绑定的值为真值的时候,节点正常渲染;当为假值的时候,节点仍旧渲染,但是添加了 style="display:none;",将节点通过 CSS 的方式隐藏。渲染结果如下:

<div id="app">
  <div style="display: none;">c4</div>
</div>

相比于 v-if,v-show 其实不管在什么条件下,一开始都会进行节点的渲染,而后续的状态切换都是基于 CSS 实现的。针对状态需要频繁切换状态的节点,v-show 相对于直接修改 DOM 节点的 v-if 有更好的性能。

然而,v-show 的缺点也是显而易见的,不管初始条件如何,它都将进行 DOM 节点的渲染,这对首屏加载优化不一定是个好事情。

(2)key

在使用 v-if 等指令的时候,vue 会尽可能地复用已经渲染的元素,而不是全部地重头渲染。例如一对绑定 v-if 与 v-else 的元素,如果二者内部 DOM 元素相同,则可能在所绑定数据改变时,只更新绑定了的属性,其它通过用户操作或者 JS 修改了的属性将被保留。

<div id="app">
  <form>
    <div class="input-group" v-if="name">
      <label for="name">name:</label>
      <input type="text" name="name" placeholder="user name" />
    </div>

    <div class="input-group" v-else>
      <label for="email">email:</label>
      <input type="text" name="email" placeholder="email" />
    </div>

    <button v-on:click.prevent="toggle">toggle</button>
  </form>
</div>
......
var app = new Vue({
  el: '#app',
  data: {
    name: true
  },
  methods: {
    toggle: function () {
      this.name = ! this.name;
    }
  }
});

这里就是如此,点击 toggle 按钮的时候,v-if 所绑定的值会切换,相应的,DOM 节点也会跟着切换,但是实际上,由于 vue 重用了 input 元素,切换的同时,用户填写的内容并没有被清空。同理,label 元素在切换的工程中,其实也只是修改了 for 属性和元素内的文字,并没有销毁原有 DOM 节点和生成新的 DOM节点。

但是 vue 做的这种优化并不总是为人们所需要的,不需要它的时候,我们为这个元素添加一个唯一的 key 值就可以了。

<div id="app">
  <form>
    <div class="input-group" v-if="name">
      <label for="name">name:</label>
      <input type="text" name="name" placeholder="user name" key="name" />
    </div>

    <div class="input-group" v-else>
      <label for="email">email:</label>
      <input type="text" name="email" placeholder="email" key="email" />
    </div>

    <button v-on:click.prevent="toggle">toggle</button>
  </form>
</div>
......
var app = new Vue({
  el: '#app',
  data: {
    name: true
  },
  methods: {
    toggle: function () {
      this.name = ! this.name;
    }
  }
});

像这样,为这两个不需要“优化”的 input 元素添加了唯一标识的 key 以后,vue 便不会再复用这两个元素。每次切换之后,修改的内容将不会被保留。

三、更多思考

(1)基于标签的指令(v-bind 、v-if)

Handlebars 的 helpers 有自己独立的语法,比如:

{{#if ok}}
 <h1>Yes</h1>
{{/if}}

它定义了一组自己的语法。而实现同样的功能,vue 使用类似于 v-bind、v-if 之类的指令,它们都是绑定在一个个标签上面的,如

<h1 v-if="ok">Yes</h1>

这样的语法更加简洁、清晰。

Handlebars 的语法,支持同时绑定多个 DOM 节点。

{{#if ok}}
 <h1>Yes</h1>
 <h1>Yes</h1>
 <h1>Yes</h1>
{{/if}}

按照前面的思路,难道 vue 要实现成这样?

<h1 v-if="ok">Yes</h1>
<h1 v-if="ok">Yes</h1>
<h1 v-if="ok">Yes</h1>

那根本不可能,添加额外的 DOM 节点包裹住它们?那就更不可能。vue 扩展了一个 template 节点,使用的时候,我们可以像 HTML 节点一样去使用它,但是渲染页面的时候,它不会被渲染在页面上。于是,前面的代码可以实现成这样:

<template v-if="ok">
 <h1>Yes</h1>
 <h1>Yes</h1>
 <h1>Yes</h1>
</template>

想想,其实和 Handlebars 也差不多了,甚至显得还要复杂些了,毕竟 template 这个单词这么长~

(2)利用条件渲染字符串

前面说,v-if 等指令都是基于标签的,那如果我不想创建额外的标签,只是想按照条件去修改一个字符串呢?没错,你猜对了,template 节点,它里面除了可以存放节点,也可以直接存放字符串,就像这样:

<div id="app">
  <template v-if="c3">text</template>
</div>
......
var app = new Vue({
  el: '#app',
  data: {
    c3: true
  }
});

渲染结果:

<div id="app">text</div>

这里其实也就是利用了 template 节点不会被渲染在页面上的特性。

(3)属性的“条件渲染”

既然 HTML 节点可以条件渲染,多个 HTML 节点可以条件渲染,HTML 节点内字符串可以条件渲染,那么 HTML 属性呢?在编写模板的时候,HTML 属性其实也是字符串,我们能想上面那样,利用 template 模板创建字符串作为 HTML 的属性吗?

<div title="<template v-if='c3'>title content</template>">此处应有 title</div>

是不是一看就感觉怪怪的?vue 也这样觉得,于是控制台里就解析成了:

<div title="<template v-if='c3'>title content</template>">此处应有 title</div>

中间的 <template v-if='c3'>title content</template> 整个的被识别成了字符串,那如果去掉外面的双引号呢?

<div title=<template v-if='c3'>title content</template>>此处应有 title</div>

好像看起来更奇怪了。最后的渲染结果:

<div title="<template">title content>此处应有 title</div>

vue 的模板解析不是简单的依赖于字符串的解析,所以其实这里不能使用这种方法。正确的姿势是利用 v-bind 指令:

<div v-bind:title="c3 ? 'title content' : '' ">title</div>

因为 v-bind 指令的预期值实际上可以接受 js 表达式的,这里我们传入了一个条件表达式。当 c3 为真值的时候,渲染为 title="title content",当 c3 为假值的时候,渲染为 title=""。

Javascript 相关文章推荐
javascript 自定义事件初探
Aug 21 Javascript
基于jquery创建的一个图片、视频缓冲的效果样式插件
Aug 28 Javascript
javascript制作loading动画效果 loading效果
Jan 14 Javascript
JavaScript跨域方法汇总
Oct 16 Javascript
jquery中EasyUI使用技巧小结
Feb 10 Javascript
jQuery同步提交示例代码
Dec 12 Javascript
解决bootstrap中使用modal加载kindeditor时弹出层文本框不能输入的问题
Jun 05 Javascript
微信小程序“摇一摇”的实例代码
Jul 20 Javascript
vue-cli webpack模板项目搭建及打包时路径问题的解决方法
Feb 26 Javascript
详解JWT token心得与使用实例
Aug 02 Javascript
vue实现侧边栏导航效果
Oct 21 Javascript
VSCode launch.json配置详细教程
Jun 18 Javascript
vue.js 上传图片实例代码
Jun 22 #Javascript
详解Angular 开发环境搭建
Jun 22 #Javascript
详解Angular2组件之间如何通信
Jun 22 #Javascript
Angular2 父子组件数据通信实例
Jun 22 #Javascript
详解Angular之constructor和ngOnInit差异及适用场景
Jun 22 #Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
Jun 22 #Javascript
文本溢出插件jquery.dotdotdot.js使用方法详解
Jun 22 #jQuery
You might like
PHP获取数组中重复最多的元素的实现方法
2014/11/11 PHP
php强制下载文件函数
2016/08/24 PHP
PHP基于imagick扩展实现合成图片的两种方法【附imagick扩展下载】
2017/11/14 PHP
javascript 一个函数对同一元素的多个事件响应
2009/07/25 Javascript
JavaScript DOM学习第一章 W3C DOM简介
2010/02/19 Javascript
关于javascript模块加载技术的一些思考
2014/11/28 Javascript
js使用心得分享
2015/01/13 Javascript
jQuery监控文本框事件并作相应处理的方法
2015/04/16 Javascript
Bootstrap每天必学之级联下拉菜单
2016/03/27 Javascript
全面解析bootstrap格子布局
2016/05/22 Javascript
Bootstrap框架结合jQuery仿百度换肤功能实例解析
2016/09/17 Javascript
Bootstrap 设置datetimepicker在屏幕上面弹出设置方法
2017/03/21 Javascript
mint-ui的search组件在键盘显示搜索按钮的实现方法
2017/10/27 Javascript
nodejs实现简单的gulp打包
2017/12/21 NodeJs
vue watch普通监听和深度监听实例详解(数组和对象)
2018/08/16 Javascript
Vue模拟数据,实现路由进入商品详情页面的示例
2018/08/31 Javascript
Node.js 如何利用异步提升任务处理速度
2019/01/07 Javascript
深入探讨JavaScript的最基本部分之执行上下文
2019/02/12 Javascript
使用webpack5从0到1搭建一个react项目的实现步骤
2020/12/16 Javascript
浅谈Vue开发人员的7个最好的VSCode扩展
2021/01/20 Vue.js
[01:14:35]DOTA2上海特级锦标赛B组资格赛#1 Alliance VS Fnatic第一局
2016/02/26 DOTA
在RedHat系Linux上部署Python的Celery框架的教程
2015/04/07 Python
python 中的list和array的不同之处及转换问题
2018/03/13 Python
python抓取多种类型的页面方法实例
2019/11/20 Python
python 实现矩阵填充0的例子
2019/11/29 Python
Django 后台带有字典的列表数据与页面js交互实例
2020/04/03 Python
Python下载网易云歌单歌曲的示例代码
2020/08/12 Python
python lambda的使用详解
2021/02/26 Python
飞利浦法国官网:Philips法国
2019/07/10 全球购物
Sandro法国官网:法国成衣品牌
2019/08/28 全球购物
揠苗助长教学反思
2014/02/04 职场文书
初中生评语大全
2014/04/24 职场文书
保密工作承诺书
2014/08/29 职场文书
夏洛特的网观后感
2015/06/15 职场文书
平凡的世界读书笔记
2015/06/25 职场文书
Python语言内置数据类型
2022/02/24 Python