Vue速通(2)

常用语法与指令

Vue 常用模板语法和指令

大多数情况下,Vue 使用基于 HTML 的模板语法进行开发。在模板中,允许开发者以声明式的方式将 DOM 和组件实例的数据绑定在一起。在底层的实现中,Vue 将模板编译成虚拟 DOM 渲染函数。

指令由v-作为前缀,表明它们是一些由 Vue 提供的特殊 attribute,它们将为渲染的 DOM 应用特殊的响应式行为。

Mustache

如果我们希望把数据显示到模板(template)中,使用最多的语法是 Mustache 语法(双大括号)的文本插值。Mustache 中不仅仅可以是 data 中的属性,也可以是一个 JavaScript 的表达式。例如:{{ formatDate(date).split("-") }}

v-bind

v-bind(:)动态地绑定一个或多个 attribute,或一个组件 prop 到表达式。

绑定属性如:v-bind:src="imgUrl":href="url"

绑定 class 如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<div id="app">
  <!-- 1.基本绑定class -->
  <p :class="className">Hello World</p>

  <!-- 2.动态class可以语句 -->
  <p :class="isActive ? 'active': ''">Hello World</p>

  <!-- 3.对象语法绑定对象 -->
  <p :class="{ active: isActive }">Hello World</p>

  <!-- 2.2.对象语法的多个键值对 -->
  <p :class="{ active: isActive, show: isShow }">Hello World</p>

  <!-- 2.3.动态绑定的class是可以和普通的class同时的使用 -->
  <p class="active" :class="{ show: isShow }">Hello World</p>

  <!-- 2.4.动态绑定的class是可以和普通的class同时的使用 -->
  <p class="active" :class="getDynamicClasses()">Hello World</p>

  <!-- 3.动态class可以写数组语法 -->
  <p :class="['active', 'show']">Hello World</p>
  <p :class="['active', className]">Hello World</p>
  <p :class="['active', isShow ? 'show': '']">Hello World</p>
  <h2 :class="['active', { show: isShow }]">Hello World</p>
</div>

绑定 style 如:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<div id="app">
  <!-- 1.普通的html写法 -->
  <p style="color: red; font-size: 30px;">Hello World</p>

  <!-- 2.style中的某些值, 来自data中 -->
  <!-- 2.1.动态绑定style, 在后面跟上 对象类型 (重要)-->
  <p v-bind:style="{ color: fontColor, 'font-size': fontSize + 'px' }">
    Hello World
  </p>
  <!-- 2.2.动态的绑定属性, 这个属性是一个对象 -->
  <p :style="objStyle">Hello World</p>

  <!-- 3.style的数组语法 -->
  <p :style="[objStyle, { fontSize: fontSize + 'px'  }]">Hello World</p>
</div>

绑定属性名如:<p :[name]="'active'">Hello World</p>

绑定对象:使用 v-bind 绑定一个对象,将一个对象的所有属性,绑定到元素上的所有属性。如:<p v-bind="infos">Hello World</p>

v-on

v-on:(@)监听用户发生的事件,比如点击、拖拽、键盘事件等等。

当通过 methods 中定义方法,需要注意参数问题:如果该方法不需要额外参数,那么方法后的()可以不添加,但如果方法本身会默认将原生事件 event 参数传递进去.如果需要同时传入某个参数和 event 时,可以通过$event 传入事件。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<div id="app">
  <div v-on:click="divClick"></div>
  <div @mousemove="divMousemove()"></div>

  <span>{{ counter }}</span>
  <button @click="increment">+1</button>

  <div
    class="box"
    @click="divClick(args1)"
    @mousemove="divMousemove(args1, $event)"
  ></div>
  <!-- <div class="box" v-on="{ click: divClick, mousemove: divMousemove }"></div> -->
  <!-- <div class="box" @="{ click: divClick, mousemove: divMousemove }"></div> -->
</div>

v-on 支持修饰符,修饰符相当于对事件进行了一些特殊的处理:

  .stop - 调用 event.stopPropagation()。
  .prevent - 调用 event.preventDefault()。
  .capture - 添加事件侦听器时使用 capture 模式。
  .self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
  .{keyAlias} - 仅当事件是从特定键触发时才触发回调。
  .once - 只触发一次回调。
  .left - 只当点击鼠标左键时触发。
  .right - 只当点击鼠标右键时触发。
  .middle - 只当点击鼠标中键时触发。
  .passive - { passive: true } 模式添加侦听器

v-model

v-model 指令用来在代码逻辑中获取到用户提交的数据,它会根据控件类型自动选取正确的方法来更新元素。v-model 本质上不过是语法糖,负责监听用户的输入事件来更新数据。官方有说到,v-model 的原理其实是背后有两个操作:1. v-bind 绑定 value 属性的值; 2. v-on 绑定 input 事件监听到函数中,函数会获取最新的值赋值到绑定的属性中。

v-model 可以绑定 input、textarea、checkbox、radio、select:

1
2
3
<label for="account">
  账号:<input id="account" type="text" v-model="account" />
</label>
1
2
3
4
5
<textarea cols="30" rows="10" v-model="content"></textarea>
<!-- checkbox单选框: 绑定到属性中的值是一个Boolean -->
<label for="agree">
  <input id="agree" type="checkbox" v-model="isAgree" /> 同意协议
</label>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<!-- checkbox多选框: 绑定到属性中的值是一个Array -->
<!-- 注意: 多选框当中, 必须明确的绑定一个value值 -->
<div class="hobbies">
  <h2>请选择你的爱好:</h2>
  <label for="sing">
    <input id="sing" type="checkbox" v-model="hobbies" value="sing" /></label>
  <label for="jump">
    <input id="jump" type="checkbox" v-model="hobbies" value="jump" /></label>
  <label for="rap">
    <input id="rap" type="checkbox" v-model="hobbies" value="rap" /> rap
  </label>
  <label for="basketball">
    <input
      id="basketball"
      type="checkbox"
      v-model="hobbies"
      value="basketball"
    />
    篮球
  </label>
  <h2>爱好: {{hobbies}}</h2>
</div>
1
2
3
4
5
6
<label for="male">
  <input id="male" type="radio" v-model="gender" value="male" /></label>
<label for="female">
  <input id="female" type="radio" v-model="gender" value="female" /></label>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
<!-- select的单选 -->
<select v-model="fruit">
  <option value="apple">苹果</option>
  <option value="orange">橘子</option>
  <option value="banana">香蕉</option>
</select>

<!-- select的多选 -->
<select multiple size="3" v-model="fruits">
  <option value="apple">苹果</option>
  <option value="orange">橘子</option>
  <option value="banana">香蕉</option>
</select>

在真实开发中,从后端接口获得数据后,绑定到 data 返回的对象中,再通过 v-bind 来进行值的绑定,这个过程就是 v-model 的值绑定。

v-model修饰符

lazy:使用v-model.lazy修饰符,会将绑定的事件切换为change事件,只有在提交时(比如回车)才会触发。

number:使用v-model.number修饰符,将绑定值的默认String类型改为Number类型。

trim: 使用v-model.trim修饰符,自动过滤用户输入的空白字符。

v-for

v-for 类似于 JavaScript 的 for 循环,可以用于遍历可迭代对象。

v-for 的基本格式是v-for="item in Array",item 可以用元素别名进行自定义。在遍历一个数组的时候会经常需要拿到数组的索引,如果需要索引,可以使用格式:v-for="(item, index) in Array"

v-for 也支持遍历对象,并且支持最多三个参数:

一个参数: v-for="value in object";
二个参数: v-for="(value, key) in object";
三个参数: v-for="(value, key, index) in object";

类似于 v-if,template 元素来循环渲染一段包含多个元素的内容。

Vue 将被侦听的数组的变更方法进行了包裹,所以它们也将会触发视图更新。被包裹过的方法包括:

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

但是某些方法不会替换原来的数组,而是会生成新的数组,比如 filter()、concat()和 slice()等,故而不会被侦听,需要将新数组赋值给原数组。

在使用 v-for 进行列表渲染时,通常需要给元素或者组件绑定一个 key 属性。在进行插入或者重置顺序的时候,保持相同的 key 可以让 diff 算法更加的高效。

v-if、v-else、v-else-if、v-show

v-if、v-else、v-else-if 用于根据条件来渲染某一块的内容,这些内容只有在条件为 true 时,才会被渲染出来;这三个指令与 JavaScript 的条件语句 if、else、else if 类似;

v-if 是惰性的;当条件为 false 时,其判断的内容完全不会被渲染或者会被销毁掉;当条件为 true 时,才会真正渲染条件块中的内容;

v-show 和 v-if 的用法看起来是一致的,也是根据一个条件决定是否显示元素或者组件,但实际并不相同。

首先,在用法上的区别:v-show 是不支持 template;v-show 不可以和 v-else 一起使用;其次,本质的区别:v-show 元素无论是否需要显示到浏览器上,它的 DOM 实际都是有存在的,只是通过 CSS 的 display 属性来进行切换;v-if 当条件为 false 时,其对应的原生压根不会被渲染到 DOM 中。

如果我们的原生需要在显示和隐藏之间频繁的切换,那么使用 v-show;如果不会频繁的发生切换,那么使用 v-if。

其它 Vue 指令

v-html

默认情况下,如果我们展示的内容本身是 html 的,那么 vue 并不会对其进行特殊的解析。如果我们希望这个内容被 Vue 可以解析出来,那么可以使用 v-html 来展示。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<div id="app">
  <h2>{{ text }}</h2>
  <h2 v-html="text"></h2>
</div>

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
  const app = Vue.createApp({
    data: function() {
      return {
        text: `<p style="color: red">这是一段红色的文本。</p>`
      }
    },
  })
  app.mount("#app")
</script>

在网站上动态渲染任意 HTML 是非常危险的,因为这非常容易造成 XSS 漏洞。请仅在内容安全可信时再使用 v-html,并且永远不要使用用户提供的 HTML 内容。

v-once

v-once 用于指定元素或者组件只渲染一次:当数据发生变化时,元素或者组件以及其所有的子元素将视为静态内容并且跳过,该指令可以用于性能优化。如:<p v-once>{{counter}}</p>

v-text

v-text 可以用于更新元素的 textContent,类似于 Mustache,但是没有 Mustache 灵活。如:<p v-text="counter"></p>

v-pre

v-pre 用于跳过元素和它的子元素的编译过程,显示原始的 Mustache 标签。v-pre 跳过不需要编译的节点,加快编译的速度。如:<p v-pre>{{counter}}</p>

v-cloak

v-cloak 会保持在元素上直到关联组件实例结束编译。这个指令和 CSS 规则如[v-cloak]{ display: none }一起用时,这个指令可以隐藏未编译的 Mustache 标签直到组件实例准备完毕。如:<p v-cloak>{{counter}}</p>

v-memo

v-memo 使用一个数组保存元素内特定属性,使得特定属性未发生改变时跳过该元素的更新,该指令可以用于性能优化。如:<div v-memo="[valueA, valueB]">...</div>