Vue学习笔记(二)

2019-06-03

博客的markdown解释器显示有问题,请移步github

条件渲染

v-if

  • 若truthy时渲染(truthy可以理解为if(obj==true)
  • <template>标签配合,可y以一次if很多标签(虽然和<template>本身定义的语义不太符合)

v-else

和if配合使用

<div v-if="Math.random() > 0.5">
  Now you see me
</div>
<div v-else>
  Now you don't
</div>

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>

和if配合使用

v-show

与v-if不同,v-show仅仅是控制元素的display属性。

在某些情况下(比如需要频繁进行DOM操作),显然v-show的效率更高。

在效果上,v-show和自己用v-bind:style来控制display属性的最终效果相同。

对可复用的元素加上key

Vue可以用Key来复用元素,从而决定是否重新渲染。

对Key的设计,Vue是尽可能帮你复用元素,除非Key不同,而React恰好相反。

<li key='k1'></li>

列表渲染

列表渲染指令v-for,示例如下:

<ul id="example-1">
  <li v-for="item in items">
    
  </li>
</ul>
var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})

需要注意的是:

  • Vue不推荐将v-forv-if一起使用

  • v-for支持可选的第二个参数,选项的索引

    <ul id="example-2">
      <li v-for="(item, index) in items">
         -  - 
      </li>
    </ul>
    
  • v-for除了支持遍历数组,也可以遍历对象(的属性),和for...in语法类似。此种用法支持最高三个参数:

    <div v-for="(value, name, index) in object">
      . : 
    </div>
    
  • Vue非常推荐给列表渲染时加上key

    <div v-for="item in items" v-bind:key="item.id">
      <!-- 内容 -->
    </div>
    
    • 同样地,Vue默认行为是尽可能复用组件。
    • 当无Key时,数据项的顺序被改变,Vue将不会移动DOM元素,而是就地更新。数据项大小变更,Vue将重新渲染。
    • 使用Key,Vue就可以重用和重新排序现有元素。

更新检测

数组

  • 对于变异方法(mutating method,即会改变数组本身的方法),比如pushpop,shiftunshiftsplice等方法,Vue是通过将被监听的数组的变异方法进行包裹,从而实现更新检测。

  • 对于非变异方法,比如filterconcatslice等方法,一般用法是替换法,比如

    example1.items = example1.items.filter(item=>item.message.match(/Foo/))
    

    这样主要依靠Vue的虚拟DOM来进行更新检测,通过Key复用从而提升性能

  • 对于其他数组访问方法,将不能检测到更新监听(因为JS没有运算符重载):

    • 直接用下标访问数组项vm.items[index]=newValue
    • 直接修改数组长度vm.items.length=newLength

    对于这两种数组访问,都可以使用Array.prototype.splice方法解决

    • 修改数组项vm.items.splice(index,1,newValue)
    • 修改数组长度vm.items.splice(newLength)

对象

  • 由于JavaScript的限制,Vue不能检测对象属性的添加或删除,只能检测其修改(比如Object.defineProperty方法),所以在最开始定义时,就要将对象全部响应式属性定义出来,赋值为null啥的都行。

    • 或者通过Vue.set方法,但我觉得不推荐,不够直观。提前定义vm中需要的数据,也是非常良好的习惯,对可读性的提升非常大。
    var vm = new Vue({
      data: {
        a: 1
      }
    })
    // `vm.a` 现在是响应式的
      
    vm.b = 2
    // `vm.b` 不是响应式的
    
    var vm = new Vue({
      data: {
        a: 1,
        b: null//提前定义
      }
    })
    // `vm.a` 现在是响应式的
      
    vm.b = 2
    // `vm.b` 也是响应式的
    

过滤/排序结果

许多需求是需要将列表结果通过过滤/排序重新显示,方法可以有:

  • 计算属性

    <li v-for="n in evenNumbers"></li>
    
    data: {
      numbers: [ 1, 2, 3, 4, 5 ]
    },
    computed: {
      evenNumbers: function () {
        return this.numbers.filter(function (number) {
          return number % 2 === 0
        })
      }
    }
    
  • 方法属性method

单纯重复

<!--渲染十次-->
<div>
  <span v-for="n in 10"> </span>
</div>

使用模板

类似v-if,v-for也可以配合<template>标签进行循环渲染

<ul>
  <template v-for="item in items">
    <li></li>
    <li class="divider" role="presentation"></li>
  </template>
</ul>

v-forv-if一同使用

vue不推荐在同一元素上使用v-forv-if

统一节点上的v-forv-if优先级更高。即v-if是作用于v-for的循环中,而不是判断v-for是否执行

事件处理

事件监听

使用v-on指令监听DOM事件,类似DOM0级事件

<div id="example-1">
  <button v-on:click="counter += 1">Add 1</button>
  <p>The button above has been clicked  times.</p>
</div>

当然更常见的是,将事件处理程序定义在methods属性中,而不是写在v-on指令里面。

  • 不写调用,比如v-on:click='hello',默认传入原生DOM事件event,就像原生事件监听一样。
  • 也可以写调用,v-on:click='hello("QE")',则传入自己定义的参数。

事件修饰符

我们可以使用原生的event.preventDefault()event.stopPropagation(),但Vue的事件绑定是用的DOM0级事件类似的语法。对addEventListener的支持不太好,比如在捕获阶段处理事件等。Vue推出了一些事件修饰符实现对这些功能的支持:

  • .stop=event.stopPropagation

  • .prevent=event.preventDefault

  • .capture=target.addEventListener(type,cb,true)

  • .self:检测target,仅当target是元素自身才触发(即不是点击子元素)

  • .once:只调用一次即取消订阅

  • .passive:对应target.addEventListener的Option对象中的passive属性,对于移动端性能优化有些用。

    passive: A Boolean which, if true, indicates that the function specified by listener will never call preventDefault(). If a passive listener does call preventDefault(), the user agent will do nothing other than generate a console warning. See Improving scrolling performance with passive listeners to learn more.

修饰符语法可以串联:

<a v-on:click.stop.prevent="doThat">do That</a>

而且修饰符语法的顺序是有意义的。用 v-on:click.prevent.self 会阻止所有的点击,而 v-on:click.self.prevent 只会阻止对元素自身的点击。

按键修饰符

按键修饰符用于修饰键盘事件,指定按键,即keyupkeydown事件(keypress事件已deprecated)。

<input v-on:keyup.enter="submit">

支持key valuekey code两种按键定义,上式即是key value定义,更加可读,目前在标准里也更加推荐。

vue事件优化

虽然Vue的事件类似DOM0级事件,但不会导致任何的困难。当一个ViewModel被销毁时,所有的事件处理器会自动被删除。

表单绑定

使用v-model指令在表单元素(<input><textarea><select>等)元素上创建双向数据绑定,也就是所有的Vue表单都是受控表单。实现方法类似为:

  • 监听用户输入事件,比如input事件、change事件,事件发生时更新对应vm数据
  • 监听vm数据setter(可以通过Object.defineProperty),数据改变时更新表单数据。
<input v-model="message" placeholder="edit me">
<p>Message is: </p>