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
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容