Vue——条件渲染 and 列表渲染

6 条件渲染


  1. v-if 指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回 truthy 值的时候被渲染。

    • 意思是有 v-if 这个指令的 HTML 元素及其子元素,只会在 v-if 属性值为 truthy 时才会被渲染到 DOM 结构中,否则会被删除。前面就遇到过 v-if ,这里解答了之前的疑问。
    • v-if 的值同样可以是表达式。
    • v-if 作用于 div 元素的话,子元素的效果?结论:子元素也管,管父元素的整个 DOM 树。
    • v-if 与 v-for 一起使用时,v-for 比 v-if 有更高的优先级。不推荐 v-if 与 v-for 一起使用。
  2. 在 <template> 元素上使用 v-if 条件渲染分组。<template> 元素可能算是 Vue 自定义的一个元素,它就是一个类似 <div> 这样的容器,可以容纳很多子元素,但 <template> 本身是不会渲染到 DOM 中的。在 <template> 上使用 v-if 可以控制 <template> 的所有子元素。方便!后续或许还会用到 <template>。

  3. v-else 指令。v-else 指令很容易理解,就像普通的 if-else 语句一样,和你预想的效果一样。注意 v-else 元素必须紧跟在 v-if 或 v-else-if 的元素的后面,否则它将不会被识别。

  4. v-else-if 指令。Vue 2.1.0 新增的指令。和你预想的效果一样。类似 v-else ,v-else-if 也必须紧跟在 v-if 或 v-else-if 后面。

  5. 通过下面的例子很容易理解 v-if 、v-else 、v-else-if :

    <div v-if="type === 'A'">
       A
    </div>
    <div v-else-if="type === 'B'">
      B
    </div>
    <div v-else-if="type === 'C'">
      C
    </div>
    <div v-else>
      Not A/B/C
    </div>
    
  6. 用 key 管理可复用的元素

    • Vue 会尽可能高效地渲染元素,通常会复用已用元素而不是从头开始渲染。
    • 复用元素也不总是符合实际需求。可以添加一个具有唯一值的 key attribute ,表示“这两个元素是完全独立的,不要复用它们”。详情参考:用 key 管理可复用的元素
    • 如果 key 的值一样呢?会不会报错呢?两个不同的种类的元素添加了同一个 key 值又会怎么样?待探索
  7. v-show

    • v-show 的作用效果和 v-if 类似。如果表达式返回 truthy 值,则显示该元素。
    • 但是 v-show 只是简单地切换元素的 CSS property display。带 v-show 的元素始终会被渲染并保留在 DOM 中。
    • v-show 不支持 <template> 元素,也不支持 v-else。
  8. v-if vs v-show

    • v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。

    • v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

    • 相比之下,v-show 就简单得多——不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换。

    • 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。

7 列表渲染


  1. 用 v-for 把一个数组对应为一组元素

    • v-for 指令可以基于一个数组来渲染一个列表。
    • v-for 指令需要使用 item in items 形式的特殊语法,其中 items 是源数据数组,而 item 则是被迭代的数组元素的别名。
    • v-for 还支持一个可选的第二个参数,即当前项的索引。如:<li v-for="(item, index) in items">
    • 也可以用 of 替代 in 作为分隔符
    • 是否只能在 <li> 标签上使用 v-for ?
  2. 在 v-for 里使用对象

    • 可以用 v-for 来遍历一个对象的 property。
    • 也可以提供第二个的参数为 property 名称 (也就是键名):<div v-for="(value, name) in object">
    • 上面的例子说明,v-for 并不是仅限用于 <li> 标签
    • 还可以用第三个参数作为索引:<div v-for="(value, name, index) in object">
    • 在遍历对象时,会按 Object.keys() 的结果遍历,但是不能保证它的结果在不同的 JavaScript 引擎下都一致。
  3. 维护状态

    • 当 Vue 正在更新使用 v-for 渲染的元素列表时,它默认使用“就地更新”的策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素,并且确保它们在每个索引位置正确渲染。这个类似 Vue 1.x 的 track-by="$index"。
    • 这个默认的模式是高效的,但是只适用于不依赖子组件状态或临时 DOM 状态 (例如:表单输入值) 的列表渲染输出。
    • 以上两点没看太明白。
    • 为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key attribute:<div v-for="item in items" v-bind:key="item.id">
    • 建议尽可能在使用 v-for 时提供 key attribute,除非遍历输出的 DOM 内容非常简单,或者是刻意依赖默认行为以获取性能上的提升。
    • key 是 Vue 识别节点的一个通用机制,key 并不仅与 v-for 特别关联。
    • 不要使用对象或数组之类的非基本类型值作为 v-for 的 key。请用字符串或数值类型的值。
  4. 数组更新检测

    • 变更方法, Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。这些被包裹过的方法包括:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
    • 替换数组。相比之下,也有非变更方法,例如 filter()、concat() 和 slice()。它们不会变更原始数组,而总是返回一个新数组。当使用非变更方法时,可以用新数组替换旧数组。
    • 由于 JavaScript 的限制,Vue 不能检测数组和对象的变化。
    • 迷惑了吧?
    • 不是说侦听了数组的变更方法吗,不是说替换数组也行吗?怎么就不能检测数组和对象的变化。
    • 其实是————Vue 不能检测以下数组的变动:当你利用索引直接设置一个数组项时,例如:vm.items[indexOfItem] = newValue。当你修改数组的长度时,例如:vm.items.length = newLength。详情参见:深入响应式原理
  5. “显示”过滤/排序的结果

    • 这里“显示”的意思就是展示。0.0
    • 有时,我们想要显示一个数组经过过滤或排序后的版本,而不实际变更或重置原始数据。在这种情况下,可以创建一个计算属性,来返回过滤或排序后的数组。例如:
      <li v-for="n in evenNumbers">{{ n }}</li>
      
      data: {
       numbers: [ 1, 2, 3, 4, 5 ]
      },
      computed: {
       evenNumbers: function () {
         return this.numbers.filter(function (number) {
           return number % 2 === 0
         })
       }
      }
      
    • 在计算属性不适用的情况下 (例如,在嵌套 v-for 循环中) 你可以使用一个方法。例如:
      <ul v-for="set in sets">
       <li v-for="n in even(set)">{{ n }}</li>
      </ul>
      
      data: {
       sets: [[ 1, 2, 3, 4, 5 ], [6, 7, 8, 9, 10]]
      },
      methods: {
       even: function (numbers) {
         return numbers.filter(function (number) {
           return number % 2 === 0
         })
       }
      }
      
  6. v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。例如:

    <div>
      <span v-for="n in 10">{{ n }} </span>
    </div>
    
  7. 在 <template> 上使用 v-for。类似于 v-if,你也可以利用带有 v-for 的 <template> 来循环渲染一段包含多个元素的内容。比如:

    <ul>
      <template v-for="item in items">
        <li>{{ item.msg }}</li>
        <li class="divider" role="presentation"></li>
      </template>
    </ul>
    
  8. v-for 与 v-if 一同使用

    • 不推荐在同一元素上使用 v-if 和 v-for。
    • 当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:
      <li v-for="todo in todos" v-if="!todo.isComplete">
       {{ todo }}
      </li>
      
    • 而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>) 上。
      <ul v-if="todos.length">
       <li v-for="todo in todos">
         {{ todo }}
       </li>
      </ul>
      <p v-else>No todos left!</p>
      
  9. 在组件上使用 v-for

    • 在自定义组件上,你可以像在任何普通元素上一样使用 v-for。
      <my-component v-for="item in items" :key="item.id"></my-component>
      
    • 然而,任何数据都不会被自动传递到组件里,因为组件有自己独立的作用域。为了把迭代数据传递到组件里,我们要使用 prop:
      <my-component
       v-for="(item, index) in items"
       v-bind:item="item"
       v-bind:index="index"
       v-bind:key="item.id"
      ></my-component>
      
    • 在组件上使用 v-for
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,711评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,932评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,770评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,799评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,697评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,069评论 1 276
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,535评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,200评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,353评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,290评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,331评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,020评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,610评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,694评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,927评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,330评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,904评论 2 341

推荐阅读更多精彩内容