[TOC]

Vue2 备忘清单

渐进式 JavaScript 框架 Vue 2 备忘清单的快速参考列表,包含常用 API 和示例。

入门

介绍

Vue 是一套用于构建用户界面的渐进式框架

注意:Vue 2.x 版本对应 Vue Router 3.x 路由版本

快速创建 Vue 项目 (Vue CLI)

npx @vue/cli create hello-world

声明式渲染

<div id="app">
  {{ message }}
</div>

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

基础例子

<div id="example">
  <p>原始信息: "{{ message }}"</p>
  <p>
    计算的反向信息: "{{ reversedMessage }}"
  </p>
</div>

var vm = new Vue({
  el: '#example',
  data: {
    message: 'Hello'
  },
  computed: {
    // 计算属性的 getter
    reversedMessage: function () {
      // `this` 指向 vm 实例
      return this.message.split('')
          .reverse().join('')
    }
  }
})

结果

原始信息:  "Hello"
计算的反向信息:  "olleH"

绑定元素属性

<div id="app-2">
  <span v-bind:title="message">
    鼠标悬停几秒钟查看此处动态绑定的提示信息!
  </span>
</div>

var app2 = new Vue({
  el: '#app-2',
  data: {
    message: '页面加载于 ' + new Date()
        .toLocaleString()
  }
})

条件

<div id="app-3">
  <p v-if="seen">现在你看到我了</p>
</div>

var app3 = new Vue({
  el: '#app-3',
  data: {
    seen: true
  }
})

控制切换一个元素是否显示

循环

<div id="app-4">
  <ol>
    <li v-for="todo in todos">
      {{ todo.text }}
    </li>
  </ol>
</div>

var app4 = new Vue({
  el: '#app-4',
  data: {
    todos: [
      { text: '学习 JavaScript' },
      { text: '学习 Vue' },
      { text: '整个牛项目' }
    ]
  }
})

点击事件处理

<div id="app-5">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">
    反转消息
  </button>
</div>

var app5 = new Vue({
  el: '#app-5',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('')
            .reverse().join('')
    }
  }
})

输入事件处理

<div id="app-6">
  <p>{{ message }}</p>
  <input v-model="message">
</div>

v-model 指令,它能轻松实现表单输入和应用状态之间的双向绑定

var app6 = new Vue({
  el: '#app-6',
  data: {
    message: 'Hello Vue!'
  }
})

模板语法

文本

<span>Message: {{ msg }}</span>
<span v-once>
  这个将不会改变: {{ msg }}
</span>

使用 v-once 指令,执行一次性地插值,当数据改变时,插值处的内容不会更新

原始 HTML

<p>解释为普通文本: {{ rawHtml }}</p>
<p>
  使用 v-html 指令: 
  <span v-html="rawHtml"></span>
</p>

使用 v-html 指令,输出真正的 HTML

属性

<div v-bind:id="dynamicId"></div>
<button v-bind:disabled="isDisabled">
  Button
</button>

如果 isDisabled 的值是 null/undefined/false 则 disabled 不会被渲染出来

JavaScript 表达式

<div id="app">
  <span>消息: {{ msg }}</span>
  <span>{{ msg + '这是字符串' }}</span>
  <span>{{ isWorking ? '是':'否' }}</span>
  <span>{{ msg.getDetials() }}</span>
  <div v-bind:id="'list-' + id"></div>
<div>

指令

<p v-if="seen">
  现在你看到我了
</p>

v-if 指令将根据表达式 seen 的值的真假来插入/移除 \

元素

指令参数

<a v-bind:href="url">...</a>

v-bind 指令将该元素 href 属性与表达式 url 的值绑定

<a v-on:click="doSomething">...</a>

v-on 指令,用于监听 DOM 事件,oSomething 是事件名

指令动态参数 v2.6

<a v-on:[eventName]="doSomething">...</a>

eventName 的值为 focus 时,v-on:[eventName] 将等价于 v-on:focus

指令修饰符

<form v-on:submit.prevent="onSubmit">
  ...
</form>

.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()

指令缩写

<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
<!-- 动态参数的缩写 (2.6.0+) -->
<a :[key]="url"> ... </a>

Class 与 Style 绑定

对象语法

<div v-bind:class="{ active: isActive }">

</div>

传给 v-bind:class 一个对象,以动态地切换 class

与普通的 class 属性共存

```html {2}

如下 datajs data: { isActive: true, hasError: false } 结果渲染为html
### 绑定的数据对象不必内联定义在模板里 <!--rehype:wrap-class=row-span-3-->html
如下 datajs data: { classObject: { active: true, ‘text-danger’: false } } 结果渲染为html
### 三元表达式html
### 数组html
### 数组语法html
如下 datajs data: { activeClass: ‘active’, errorClass: ‘text-danger’ } 结果渲染为html
### 内联样式html
如下 datajs data: { activeColor: ‘red’, fontSize: 30 } 结果渲染为html
### 内联样式对象通常更好html
如下 datajs data: { styleObject: { color: ‘red’, fontSize: ‘13px’ } } 同样的,对象语法常常结合返回对象的计算属性使用 ### 内联样式数组语法html
### 内联样式多重值html
条件渲染 --- ### v-ifhtml

Vue is awesome!

Oh no 😢

### v-else-if <!--rehype:wrap-class=row-span-2-->html
A
B
C
Not A/B/C
`@2.1.0` 新增,必须紧跟在带 `v-if` 或者 `v-else-if` 的元素之后 ### v-else <!--rehype:wrap-class=row-span-2-->html
现在你看到我了
现在你看不见我了
`v-else` 元素必须紧跟在带 `v-if` 或者 `v-else-if` 的元素的后面 ### \<template> 上使用 v-if 条件渲染分组html ### 用 key 管理可复用的元素 <!--rehype:wrap-class=col-span-2-->html ### v-showhtml

Hello!

带有 `v-show` 的元素始终会被渲染并保留在 DOM 中,只是简单地切换元素的 `CSS` 属性 `display` 列表渲染 --- ### v-forhtml {3}
  • {{ item.message }}
```js var example1 = new Vue({ el: '#example-1', data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } }) ### v-for 可选的第二个参数(索引) html {2} <li v-for="(item, index) in items"> {{ index }} {{ item.message }} </li> 如下 data js data: { items: [ { message: 'Foo' }, { message: 'Bar' } ] } 也可以用 of 替代 in 作为分隔符 html <div v-for="item of items"></div> ### v-for 使用对象 html <li v-for="value in object"> {{ value }} </li> 如下 data js data: { object: { title: 'How to do lists in Vue', author: 'Jane Doe', publishedAt: '2016-04-10' } } 渲染结果 How to do lists in Vue Jane Doe 2016-04-10 提供第二个的参数为 property 名称 (也就是键名) html <div v-for="(value, name) in object"> {{ name }}: {{ value }} </div> 还可以用第三个参数作为索引 html <div v-for="(value,name,index) in object"> {{ index }}. {{ name }}: {{ value }} </div> ### v-for/v-if html {2,3} <li v-for="todo in todos" v-if="!todo.isComplete" > {{ todo }} </li> 只渲染未完成的 todo,下面加上 v-else 示例 html <ul v-if="todos.length"> <li v-for="todo in todos"> {{ todo }} </li> </ul> <p v-else>No todos left!</p> ### 组件上使用 v-for html <my-component v-for="(item, index) in items" v-bind:item="item" v-bind:index="index" v-bind:key="item.id" ></my-component> 2.2.0+ 的版本里,当在组件上使用 v-for 时,key 现在是必须的 事件处理 —- ### 监听事件 html {2} <div id="example-1"> <button v-on:click="counter += 1"> +1 </button> <p>按钮已被点击 {{ counter }} 次。</p> </div> js var example1 = new Vue({ el: '#example-1', data: { counter: 0 } }) ### 事件处理方法 html {3} <div id="example-2"> <!-- `greet` 是在下面定义的方法名 --> <button v-on:click="greet"> 你好 </button> </div> js var example2 = new Vue({ el: '#example-2', data: { name: 'Vue.js' }, // 在 `methods` 对象中定义方法 methods: { greet: function (event) { // `this` 在方法里指向当前 Vue 实例 alert('Hello ' + this.name + '!') // `event` 是原生 DOM 事件 if (event) { alert(event.target.tagName) } } } }) 也可以用 JavaScript 直接调用方法 js example2.greet() // => 'Hello Vue.js!' ### 内联处理器中的方法 html {2,5} <div id="example-3"> <button v-on:click="say('hi')"> 弹出 hi </button> <button v-on:click="say('what')"> 弹出 what </button> </div> js {4} new Vue({ el: '#example-3', methods: { say: function (message) { alert(message) } } }) 访问原始的 DOM 事件,用特殊变量 $event html <button v-on:click="say('what', $event)"> 提交 </button> js methods: { say: function (message, event) { // 现在我们可以访问原生事件对象 if (event) { event.preventDefault() } alert(message) } } ### 事件修饰符 html <!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="submit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件监听器时使用事件捕获模式 --> <!-- 即内部元素触发的事件先在此处理 --> <!-- 然后交由内部元素进行处理 --> <div v-on:click.capture="doThis">...</div> <!-- 当 event.target 是当前元素自身时触发 --> <!-- 即事件不是从内部元素触发的 --> <div v-on:click.self="doThat">...</div> <!-- 点击事件将只会触发一次 --> <a v-on:click.once="doThis"></a> ### 事件修饰符 passive html <!-- 滚动事件的默认行为(即滚动行为)会立即触发 --> <!-- 而不会等待 `onScroll` 完成 --> <!-- 包含 event.preventDefault() 的情况 --> <p v-on:scroll.passive="onScroll"> ... </p> 这个 .passive 修饰符尤其能够提升移动端的性能。 ### 按键修饰符 html <!-- 在 key 是 Enter 时调用 vm.submit() --> <input v-on:keyup.enter="submit"> <!-- 在 key 是 PageDown 时被调用 --> <input v-on:keyup.page-down="onPageDown"> <!-- Alt + C --> <input v-on:keyup.alt.67="clear"> <!-- Ctrl + Click --> <div v-on:click.ctrl="doSomething"> ### .exact 修饰符 html <!-- 即使 Alt 或 Shift 被一同按下时也会触发 --> <button v-on:click.ctrl="onClick"> <!-- 有且只有 Ctrl 被按下的时候才触发 --> <button v-on:click.ctrl.exact="ctrlClick"> <!-- 没有任何系统修饰符被按下的时候才触发 --> <button v-on:click.exact="onClick"> 计算属性和侦听器 —- ### 基础例子 html <div id="example"> <p>Original message: "{{ message }}"</p> <p> 计算的反向消息: "{{ reversedMessage }}" </p> </div> js var vm = new Vue({ el: '#example', data: { message: 'Hello' }, computed: { // 计算属性的 getter reversedMessage: function () { // `this` 指向 vm 实例 return this.message.split('') .reverse().join('') } } }) ### 计算属性缓存 vs 方法 html <p> 计算的反向消息:"{{ reversedMessage() }}" </p> 在组件中,我们可以将同一函数定义为一个方法而不是一个计算属性 js methods: { reversedMessage: function () { return this.message.split('') .reverse().join('') } } 两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。 ### 计算属性 vs 侦听属性 html <div id="demo">{{ fullName }}</div> js var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function (val) { this.fullName = val + ' ' + this.lastName }, lastName: function (val) { this.fullName = this.firstName + ' ' + val } } }) 上面代码是命令式且重复的。将它与计算属性的版本进行比较: js var vm = new Vue({ el: '#demo', data: { firstName: 'Foo', lastName: 'Bar' }, computed: { fullName: function () { return this.firstName + ' ' + this.lastName } } }) ### 计算属性的 setter js computed: { fullName: { get: function () { // getter return this.firstName + ' ' + this.lastName }, set: function (newValue) { // setter var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } } 表单输入绑定 —- ### 文本 html <input v-model="msg" placeholder="编辑我"> <p>msg is: {{ msg }}</p> ### 多行文本 html {3} <span>Multiline message is:</span> <textarea v-model="message" placeholder="添加多行"></textarea> <p>{{ message }}</p> ### 复选框 html {4} <input type="checkbox" id="checkbox" v-model="checked" > <label for="checkbox">{{ checked}}</label> ### 多个复选框 html <input type="checkbox" id="jack" value="Jack" v-model="checkedNames"> <label for="jack">Jack</label> <input type="checkbox" id="john" value="John" v-model="checkedNames"> <label for="john">John</label> <input type="checkbox" id="mike" value="Mike" v-model="checkedNames"> <label for="mike">Mike</label> <br> <span>Checked names: {{ checkedNames }}</span> 如下 data js new Vue({ el: '...', data: { checkedNames: [] } }) ### 单选按钮 html <div id="example-4"> <input type="radio" id="one" value="One" v-model="picked"> <label for="one">One</label> <br> <input type="radio" id="two" value="Two" v-model="picked"> <label for="two">Two</label> <div>Picked: {{ picked }}</div> </div> —- js new Vue({ el: '#example-4', data: { picked: '' } }) ### 选择框 html <select v-model="selected"> <option disabled value="">请选择</option> <option>A</option> <option>B</option> <option>C</option> </select> <span>Selected: {{ selected }}</span> —- js new Vue({ el: '...', data: { selected: '' } }) ### 选择框(数组) html <select v-model="selected" multiple> <option>A</option> <option>B</option> <option>C</option> </select> <div>Selected: {{ selected }}</div> —- js new Vue({ el: '...', data: { selected: [] } }) ### v-for 渲染的动态选项 html {3-4} <select v-model="selected"> <option v-for="option in options" v-bind:value="option.value" > {{ option.text }} </option> </select> <span>Selected: {{ selected }}</span> —- js {6-8} new Vue({ el: '...', data: { selected: 'A', options: [ { text: 'One', value: 'A' }, { text: 'Two', value: 'B' }, { text: 'Three', value: 'C' } ] } }) ### 值绑定 html <!-- 当选中时,pc 为字符串 "a" --> <input type="radio" v-model="pc" value="a"> <!-- toggle 为 true 或 false --> <input type="checkbox" v-model="toggle"> <!-- 选中第一个选项时selected为字符串 abc --> <select v-model="selected"> <option value="abc">ABC</option> </select> ### 单选按钮 html <input type="radio" v-model="pick" v-bind:value="a"> 当选中时 js vm.pick === vm.a ### 复选框 html {3} <input type="checkbox" v-model="toggle" true-value="yes" false-value="no" > —- js // 当选中时 vm.toggle === 'yes' // 当没有选中时 vm.toggle === 'no' ### 选择框的选项 html <select v-model="selected"> <!-- 内联对象字面量 --> <option v-bind:value="{ number: 123 }"> 123 </option> </select> 当选中时 js typeof vm.selected // => 'object' vm.selected.number // => 123 ### 修饰符 html <!-- lazy:在“change”时而非“input”时更新 --> <input v-model.lazy="msg"> <!-- number:自动将用户的输入值转为数值类型 --> <input v-model.number="age" type="number"> <!-- trim:自动过滤用户输入的首尾空白字符 --> <input v-model.trim="msg"> 组件基础 —- ### 单文件组件 - 将 HTML/CSS/JS 三部分存放到一个 Hello.vue 文件中 html <template> <p>{{ title }} World!</p> </template> <script> export default { name: 'Hello', props: { title: { type: String, default: 'Hello' } }, data: function() { return { greeting: "Hello" }; } }; </script> <style scoped> p { font-size: 2em; text-align: center; } </style> - 使用 Hello.vue 组件 html <script> import Vue from "vue"; import Hello from "./Hello"; export default { components: { Hello } } </script> <template> <div> <Hello :title="'aaaa'"></Hello> </div> </template> ### 基本示例 js Vue.component('button-counter', { data: function () { return { count: 0 } }, template: ` <button v-on:click="count++"> 你点击了我 {{ count }} 次 </button> ` }) 组件是可复用的 Vue 实例 html <div id="components-demo"> <button-counter></button-counter> </div> —- js new Vue({ el: '#components-demo' }) 组件的复用 html <div id="components-demo"> <button-counter></button-counter> <button-counter></button-counter> <button-counter></button-counter> </div> ### 单个根元素 js {4} Vue.component('blog-post', { props: ['post'], template: ` <div class="blog-post"> <h3>{{ post.title }}</h3> <div v-html="post.content"></div> </div> ` }) —- html <blog-post v-for="post in posts" v-bind:key="post.id" v-bind:post="post" > </blog-post> ### 向子组件传递数据 js Vue.component('blog-post', { props: ['title'], template: '<h3>{{ title }}</h3>' }) 当值传递给一个 prop attribute 的时候,变成了组件实例的一个 property html <blog-post title="写博客"></blog-post> <blog-post title="如此有趣"></blog-post> ### data 必须是一个函数 js data: function () { return { count: 0 } } 组件的 data 选项必须是一个函数 ### 监听子组件事件 js {7} Vue.component('blog-post', { props: ['post'], template: ` <div class="blog-post"> <h3>{{ post.title }}</h3> <button v-on:click="$emit('enlarge-txt')" >放大文字 </button> <div v-html="post.content"></div> </div> ` }) —- html {3} <blog-post ... v-on:enlarge-text="postFontSize += 0.1" ></blog-post> 可以使用 $emit 的第二个参数来提供这个值 html {2} <button v-on:click="$emit('enlarge-text', 0.1)" > Enlarge text </button> 通过 $event 访问到被抛出的这个值 html {3} <blog-post ... v-on:enlarge-text="postFontSize += $event" ></blog-post> 如果这个事件处理函数是一个方法 html {3} <blog-post ... v-on:enlarge-text="onEnlargeText" ></blog-post> 那么这个值将会作为第一个参数传入这个方法 js methods: { onEnlargeText: function(enlargeAmount) { this.postFontSize += enlargeAmount } } ### 在组件上使用 v-model 自定义事件也可以用于创建支持 v-model 的自定义输入组件。 html <input v-model="searchText"> 等价于 html <input v-bind:value="searchText" v-on:input="searchText = $event.target.value" > 当用在组件上时,v-model 则会这样: html <custom-input v-bind:value="searchText" v-on:input="searchText = $event" ></custom-input> 为了让它正常工作,这个组件内的 \ 必须: - 将其 value attribute 绑定到一个名叫 valueprop 上 - 在其 input 事件被触发时,将新的值通过自定义的 input 事件抛出 —- js Vue.component('custom-input', { props: ['value'], template: ` <input v-bind:value="value" v-on:input="$emit('input', $event.target.value)" > ` }) 现在 v-model 就应该可以在这个组件上完美地工作起来了 html {2} <custom-input v-model="searchText" > </custom-input> ### 通过插槽分发内容 html <alert-box> 发生了不好的事情。 </alert-box> —- js {5} Vue.component('alert-box', { template: ` <div class="demo-alert-box"> <strong>Error!</strong> <slot></slot> </div> ` }) ### 动态组件示例 ```html
``` ### 解析 DOM 模板时的注意事项 有些 HTML 元素,诸如 `
    `、`
      `、`` 和 `` 和 `
      ``` `` 会被作为无效的内容提升到外部 --- 如果我们从以下来源使用模板的话,这条限制是不存在的 - 字符串 (例如:`template: '...'`) - 单文件组件 (`.vue`) - `