Vue语法笔记(二)

172 阅读7分钟

条件渲染

v-if v-else

v-if可以用于渲染某一个地方的内容,这块内容需要对应的指令表达式返回true才能被渲染。

    <div class="div">
        <h1 v-if="awesome">Vue is awesome!</h1>
        <h1 v-else>Oh no 😢</h1>
    </div>
        var vm = new Vue({
            el: '.div',
            data: {
                awesome: 0,
            }
        })

上面的例子中当属性awesome的值为true的时候,那么就会渲染Vue is awesome

否则就渲染oh no

template控制多个元素的渲染

v-if指令控制元素存在或者消失,但是如果要控制多个元素的话,可以跟template配合,只需要一个开关就够了

    <div class="div">
       <h1 v-if="awesome">Vue is awesome!</h1>
       <h1 v-if="awesome">Oh no 😢</h1>
   </div>
//如果想要控制这两个一起在一起不在,原本要这样写,非常麻烦

现在只需要用template包起来就行,而且重要的是template不会被浏览器所渲染

   <div class="div">
      <template v-if='awesome'>
          <h1>Vue is awesome!</h1>
          <h1>Oh no 😢</h1>
      </template>
  </div>
            el: '.div',
          data: {
              awesome: 1,
              age: 18
          }

v-else-if

上面的v-if跟v-else就是二选一,现在增加v-else-if来造成创造的逻辑 跟js一样

    <div class="div">
      <h1 v-if='awesome'>Vue is awesome!</h1>
      <h1 v-else-if="age">vue is good</h1>
      <h1 v-else>no</h1>
  </div>
        var vm = new Vue({
          el: '.div',
          data: {
              awesome: 1,
              age: 1
          }
      })

上面代码中,虽然age也是true,但是实际上并不会渲染出来,如果awesome是false,才会渲染第二层。

用key管理可复用的元素

Vue 会尽可能高效地渲染元素,通常会复用已有元素而不是从头开始渲染。

如果我们不想要复用已有元素的话,那么就可以使用key来管理,只要设定不同的key就可以了。

<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label> //这里没加key,所以依然会被复用
<input placeholder="Enter your email address" key="email-input">
</template>

上面代码中,如果不使用同一个key的话,那么就会复用<input>,这样做仅仅会改变inputplaceholder,再加上不同的key后,就表示不要复用相同的input标签。

v-show

根据条件来渲染展示元素除了v-if外,还有v-show指令,可以这样写

<h1 v-show="ok">Hello!</h1>

不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS property display。

v-if和v-show

v-if是真的条件渲染,因为它会根据切换过程对元素进行销毁或者重建,v-show是无论什么情况下都会渲染,只是改变display的值而已。

因为v-show是刚开始就渲染,而v-if是每次都渲染,从性能优化的角度来说,如果频繁切换的话,最好使用v-show,不频繁的话 使用v-if会比较好。

列表渲染

数组渲染

数组渲染可以接收两个参数,假设我们的原数组是数组,我们想要对其进行遍历,并且添加到页面中,就可以使用下面这种方法,

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

上面的意思是:原数组为items,item是代表数组中的每个元素.index则是代表数组的每个index值

vue还增加了一个功能,可以访问与vm.items同级的property

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

可以访问到父级别的property

对象渲染

对象渲染可以接收三个参数,分别是value、key、跟index

        <ul id="example-1">
          <li v-for="(value,key,index) in object">
              {{key}}:{{value}}:{{index}}
          </li>
      </ul>
        var example1 = new Vue({
          el: '#example-1',
          data: {
              object: {
                  firstName: "qiu",
                  lastName: "yanxi",
                  age: 20,
              }
          }
      })

打印结果

firstName:qiu:0

lastName:yanxi:1

age:20:2

for循环的key管理

建议尽量在for循环的时候用v-bind:key='xxx'的形式来给vue提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素。不加key使用v-for如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序,而是就地更新每个元素。

<div v-for="item in items" v-bind:key="item.id">
  <!-- 内容 -->
</div>

数组更新检测

变更方法

如果列表渲染时,数据对象是数组,那么当使用以下方法进行更新时,就会发生页面渲染更新的情况

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

上面的这些方法都会改变原数组

替换数组

替换数组的意思是说,不会改变原数组,而是返回一个新数组。 例如 filter()、concat() 和 slice()

        var vm = new Vue({
            el: '#example-1',
            data: {
                arr: [1, 2, 3]
            }
        })
        vm.arr = vm.arr.concat([4, 5, 6])

vue会根据新的数组来重用元素并渲染,而不会丢弃原来的DOM重新渲染

显示过滤/排序后的结果

有时候,我们的原数组不会发生变化,但是我们只是想展示数组的部分内容,所以就可以用computed属性来根据原数组 进行一些计算。

<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(numbers) {
    return numbers.filter(function (number) {
      return number % 2 === 0
    })
  }
}

在 v-for 里使用值范围

v-for 也可以接受整数。在这种情况下,它会把模板重复对应次数。

<div>
  <span v-for="n in 10">{{ n }} </span>
</div>

结果

1 2 3 4 5 6 7 8 9 10

<template> 上使用 v-for

类似于 v-if,你也可以利用带有 v-for 的 <template> 来循环渲染一段包含多个元素的内容。

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

v-for和v-if

v-for 和v-if可以嵌套使用,虽然官方文档并不推荐 当它们处于同一节点,v-for 的优先级比 v-if 更高,这意味着 v-if 将分别重复运行于每个 v-for 循环中。当你只想为部分项渲染节点时,这种优先级的机制会十分有用,如下:

<li v-for="todo in todos" v-if="!todo.isComplete">
 {{ todo }}
</li>

上面的代码将只渲染未完成的 todo。

而如果你的目的是有条件地跳过循环的执行,那么可以将 v-if 置于外层元素 (或 <template>) 上。如:

<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>

事件监听

v-on指令可以用于监听事件

    <div class="div">
        <button v-on:click="items.push(4)">点击</button>
        {{items}}
    </div>
            data: {
                items: [1, 2, 3],
            }

methods

由于事件处理存在复杂性,所以我们需要有一个执行函数,来当做点击事件后的回调函数。

那么就需要用到methods方法

<div id="example-2">
  <!-- `click` 是在下面定义的方法名 -->
  <button v-on:click="click">Greet</button>
</div>
        var vm = new Vue({
            el: '.div',
            data: {
                items: [1, 2, 3],
            },
            methods: {
                click() { this.items.push(4) }
            },
        })

这种方法跟第一种是一样的效果,但是优点是这种方法结构更加清晰,便于处理更多逻辑。第一种方法 从我的角度看,非常奇怪,像是html上放了一些字符串(实际上是js),所以容易令人迷惘。

内联处理器上的方法

可以在内联处理器上使用方法

<div id="example-3">
  <button v-on:click="say('hi')">Say hi</button>
  <button v-on:click="say('what')">Say what</button>
</div>
new Vue({
  el: '#example-3',
  
  methods: {
    say: function (message) {
      alert(message)
    }
  }
})

要用到event怎么办

vue内置了事件对象的api,可以使用&event,可以获取到点击事件的事件对象信息。

        <button v-on:click="click($event)">点击</button>

事件修饰符

在事件处理程序中调用 event.preventDefault() 或 event.stopPropagation() 是非常常见的需求。,vue支持直接使用修饰符来处理。

v-on的事件修饰符

  • .stop (e.stopPropagation)阻止事件传播
  • .prevent (e.preventDefault)阻止默认行为
  • .capture 事件捕获模式
  • .self 只当在 event.target 是当前元素自身时触发处理函数
  • .once 只触发一次
  • .passive 调用事件监听时采用passive选项,告诉浏览器这个监听模式下不会阻止默认行为

passive选项:假设现在在移动端触摸事件touchStart下,由于触摸事件的默认行为是滚动或者缩放屏幕,阻止默认行为是浏览器必须停止滚动,那么在执行触摸事件时,浏览器无法预先知道一个监听器会不会调用 preventDefault(),它需要等监听器执行完后,再去执行默认行为,而监听器执行是要耗时的,这样就会导致页面卡顿。所以如果实现告诉浏览器不会阻止默认行为,那么就可以提高优化效率。

按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">

你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。

<input v-on:keyup.page-down="onPageDown">

在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。

系统修饰键

可以用如下修饰符来实现仅在按下相应按键时才触发鼠标或键盘事件的监听器。

  • .ctrl
  • .alt
  • .shift
  • .meta
<!-- Ctrl + Click -->
<div v-on:click.ctrl="doSomething">Do something</div>

.exact 修饰符

.exact 修饰符允许你控制由精确的系统修饰符组合触发的事件。

<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">A</button>

<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="onCtrlClick">A</button>

<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">A</button>

鼠标按钮修饰符

  • .left
  • .right
  • .middle 这些修饰符会限制处理函数仅响应特定的鼠标按钮。

尾言

我本来看到在html上绑定事件觉得非常模糊不清,没想到vue的作者还特意写了一段话

你可能注意到这种事件监听的方式违背了关注点分离 (separation of concern) 这个长期以来的优良传统。但不必担心,因为所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上,它不会导致任何维护上的困难。实际上,使用 v-on 有几个好处:

扫一眼 HTML 模板便能轻松定位在 JavaScript 代码里对应的方法。

因为你无须在 JavaScript 里手动绑定事件,你的 ViewModel 代码可以是非常纯粹的逻辑,和 DOM 完全解耦,更易于测试。

当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何清理它们。

特意摘录一下~