渐进式 JavaScript 框架 Vue 2 备忘清单的快速参考列表,包含常用 API 和示例。
Vue 是一套用于构建用户界面的渐进式框架
注意:Vue 2.x 版本对应 Vue Router 3.x 路由版本
npx @vue/cli create hello-world
参考: Vue CLI 创建一个项目
<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 指令,执行一次性地插值,当数据改变时,插值处的内容不会更新
<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 不会被渲染出来
<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 的值的真假来插入/移除 <p> 元素
<a v-bind:href="url">...</a>
v-bind 指令将该元素 href 属性与表达式 url 的值绑定
<a v-on:click="doSomething">...</a>
v-on 指令,用于监听 DOM 事件,oSomething 是事件名
<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>
<div v-bind:class="{ active: isActive }">
</div>
传给 v-bind:class 一个对象,以动态地切换 class
<div
  class="static"
  v-bind:class="{
    active: isActive,
    'text-danger': hasError
  }"
></div>
如下 data
data: {
  isActive: true,
  hasError: false
}
结果渲染为
<div class="static active"></div>
<div v-bind:class="classObject"></div>
如下 data
data: {
  classObject: {
    active: true,
    'text-danger': false
  }
}
结果渲染为
<div class="static active"></div>
<div v-bind:class="[
  isActive ? activeClass : ''
]">
</div>
<div v-bind:class="[
  { active: isActive }, errorClass
]"></div>
<div v-bind:class="[
  activeClass, errorClass
]">
</div>
如下 data
data: {
  activeClass: 'active',
  errorClass: 'text-danger'
}
结果渲染为
<div class="active text-danger"></div>
<div v-bind:style="{
    color: activeColor,
    fontSize: fontSize + 'px'
}"></div>
如下 data
data: {
  activeColor: 'red',
  fontSize: 30
}
结果渲染为
<div style="color: red; font-size: 30px;"></div>
<div v-bind:style="styleObject"></div>
如下 data
data: {
  styleObject: {
    color: 'red',
    fontSize: '13px'
  }
}
同样的,对象语法常常结合返回对象的计算属性使用
<div v-bind:style="[
  baseStyles, overridingStyles
]"></div>
<div :style="{
  display: ['-webkit-box', 'flex']
}"></div>
<h1 v-if="awesome">Vue is awesome!</h1>
<h1 v-else>Oh no 😢</h1>
<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>
@2.1.0 新增,必须紧跟在带 v-if 或者 v-else-if 的元素之后
<div v-if="Math.random() > 0.5">
  现在你看到我了
</div>
<div v-else>
  现在你看不见我了
</div>
v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面
<template v-if="ok">
  <p>Paragraph 1</p>
</template>
<template v-if="loginType === 'username'">
  <label>Username</label>
  <input placeholder="输入用户名" key="username-input">
</template>
<template v-else>
  <label>Email</label>
  <input placeholder="输入邮箱" key="email-input">
</template>
<h1 v-show="ok">
  Hello!
</h1>
带有 v-show 的元素始终会被渲染并保留在 DOM 中,只是简单地切换元素的 CSS 属性 display
<ul id="example-1">
  <li
    v-for="item in items"
    :key="item.message">
    {{ item.message }}
  </li>
</ul>
var example1 = new Vue({
  el: '#example-1',
  data: {
    items: [
      { message: 'Foo' },
      { message: 'Bar' }
    ]
  }
})
<li v-for="(item, index) in items">
  {{ index }}
  {{ item.message }}
</li>
如下 data
data: {
  items: [
    { message: 'Foo' },
    { message: 'Bar' }
  ]
}
也可以用 of 替代 in 作为分隔符
<div v-for="item of items"></div>
<li v-for="value in object">
  {{ value }}
</li>
如下 data
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 名称 (也就是键名)
<div v-for="(value, name) in object">
  {{ name }}: {{ value }}
</div>
还可以用第三个参数作为索引
<div v-for="(value,name,index) in object">
  {{ index }}. {{ name }}: {{ value }}
</div>
<li
  v-for="todo in todos"
  v-if="!todo.isComplete"
>
  {{ todo }}
</li>
只渲染未完成的 todo,下面加上 v-else 示例
<ul v-if="todos.length">
  <li v-for="todo in todos">
    {{ todo }}
  </li>
</ul>
<p v-else>No todos left!</p>
注意: v-for 和 v-if 不推荐一起使用参考官方文档
<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 现在是必须的
<div id="example-1">
  <button v-on:click="counter += 1">
    +1
  </button>
  <p>按钮已被点击 {{ counter }} 次。</p>
</div>
var example1 = new Vue({
  el: '#example-1',
  data: {
    counter: 0
  }
})
<div id="example-2">
  <!-- `greet` 是在下面定义的方法名 -->
  <button v-on:click="greet">
    你好
  </button>
</div>
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 直接调用方法
example2.greet() // => 'Hello Vue.js!'
<div id="example-3">
  <button v-on:click="say('hi')">
    弹出 hi
  </button>
  <button v-on:click="say('what')">
    弹出 what
  </button>
</div>
new Vue({
  el: '#example-3',
  methods: {
    say: function (message) {
      alert(message)
    }
  }
})
访问原始的 DOM 事件,用特殊变量 $event
<button v-on:click="say('what', $event)">
  提交
</button>
methods: {
  say: function (message, event) {
    // 现在我们可以访问原生事件对象
    if (event) {
      event.preventDefault()
    }
    alert(message)
  }
}
<!-- 阻止单击事件继续传播 -->
<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>
<!-- 滚动事件的默认行为(即滚动行为)会立即触发 -->
<!-- 而不会等待 `onScroll` 完成  -->
<!-- 包含 event.preventDefault() 的情况 -->
<p v-on:scroll.passive="onScroll">
  ...
</p>
这个 .passive 修饰符尤其能够提升移动端的性能。
<!-- 在 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">
<!-- 即使 Alt 或 Shift 被一同按下时也会触发 -->
<button v-on:click.ctrl="onClick">
<!-- 有且只有 Ctrl 被按下的时候才触发 -->
<button v-on:click.ctrl.exact="ctrlClick">
<!-- 没有任何系统修饰符被按下的时候才触发 -->
<button v-on:click.exact="onClick">
<div id="example">
  <p>Original message: "{{ 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('')
    }
  }
})
<p>
  计算的反向消息:"{{ reversedMessage() }}"
</p>
在组件中,我们可以将同一函数定义为一个方法而不是一个计算属性
methods: {
  reversedMessage: function () {
    return this.message.split('')
                .reverse().join('')
  }
}
两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的响应式依赖进行缓存的。
<div id="demo">{{ fullName }}</div>
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
    }
  }
})
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
var vm = new Vue({
  el: '#demo',
  data: {
    firstName: 'Foo',
    lastName: 'Bar'
  },
  computed: {
    fullName: function () {
      return this.firstName 
        + ' ' + this.lastName
    }
  }
})
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]
    }
  }
}
<input v-model="msg" placeholder="编辑我">
<p>msg is: {{ msg }}</p>
<span>Multiline message is:</span>
<textarea
  v-model="message"
  placeholder="添加多行"></textarea>
<p>{{ message }}</p>
<input
  type="checkbox"
  id="checkbox"
  v-model="checked"
>
<label for="checkbox">{{ checked}}</label>
<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
new Vue({
  el: '...',
  data: {
    checkedNames: []
  }
})
<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>
new Vue({
  el: '#example-4',
  data: {
    picked: ''
  }
})
<select v-model="selected">
  <option disabled value="">请选择</option>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
  el: '...',
  data: {
    selected: ''
  }
})
<select v-model="selected" multiple>
  <option>A</option>
  <option>B</option>
  <option>C</option>
</select>
<div>Selected: {{ selected }}</div>
new Vue({
  el: '...',
  data: {
    selected: []
  }
})
<select v-model="selected">
  <option
    v-for="option in options"
    v-bind:value="option.value"
  >
    {{ option.text }}
  </option>
</select>
<span>Selected: {{ selected }}</span>
new Vue({
  el: '...',
  data: {
    selected: 'A',
    options: [
      { text: 'One', value: 'A' },
      { text: 'Two', value: 'B' },
      { text: 'Three', value: 'C' }
    ]
  }
})
<!-- 当选中时,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>
<input
  type="radio"
  v-model="pick"
  v-bind:value="a">
当选中时
vm.pick === vm.a
<input
  type="checkbox"
  v-model="toggle"
  true-value="yes"
  false-value="no"
>
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'
<select v-model="selected">
  <!-- 内联对象字面量 -->
  <option v-bind:value="{ number: 123 }">
    123
  </option>
</select>
当选中时
typeof vm.selected // => 'object'
vm.selected.number // => 123
<!-- 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 文件中
<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 组件
<script>
  import Vue from "vue";
  import Hello from "./Hello";
  export default {
    components: { Hello }
  }
</script>
<template>
  <div>
    <Hello :title="'aaaa'"></Hello>
  </div>
</template>
Vue.component('button-counter', {
  data: function () {
    return {
      count: 0
    }
  },
  template: `
    <button v-on:click="count++">
      你点击了我 {{ count }} 次
    </button>
  `
})
组件是可复用的 Vue 实例
<div id="components-demo">
  <button-counter></button-counter>
</div>
new Vue({
  el: '#components-demo'
})
组件的复用
<div id="components-demo">
  <button-counter></button-counter>
  <button-counter></button-counter>
  <button-counter></button-counter>
</div>
Vue.component('blog-post', {
  props: ['post'],
  template: `
    <div class="blog-post">
      <h3>{{ post.title }}</h3>
      <div v-html="post.content"></div>
    </div>
  `
})
<blog-post
  v-for="post in posts"
  v-bind:key="post.id"
  v-bind:post="post"
>
</blog-post>
Vue.component('blog-post', {
  props: ['title'],
  template: '<h3>{{ title }}</h3>'
})
当值传递给一个 prop attribute 的时候,变成了组件实例的一个 property
<blog-post title="写博客"></blog-post>
<blog-post title="如此有趣"></blog-post>
data 必须是一个函数data: function () {
  return {
    count: 0
  }
}
组件的 data 选项必须是一个函数
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>
  `
})
<blog-post
  ...
  v-on:enlarge-text="postFontSize += 0.1"
></blog-post>
可以使用 $emit 的第二个参数来提供这个值
<button
  v-on:click="$emit('enlarge-text', 0.1)"
>
  Enlarge text
</button>
通过 $event 访问到被抛出的这个值
<blog-post
  ...
  v-on:enlarge-text="postFontSize += $event"
></blog-post>
如果这个事件处理函数是一个方法
<blog-post
  ...
  v-on:enlarge-text="onEnlargeText"
></blog-post>
那么这个值将会作为第一个参数传入这个方法
methods: {
  onEnlargeText: function(enlargeAmount) {
    this.postFontSize += enlargeAmount
  }
}
自定义事件也可以用于创建支持 v-model 的自定义输入组件。
<input v-model="searchText">
等价于
<input
  v-bind:value="searchText"
  v-on:input="searchText = $event.target.value"
>
当用在组件上时,v-model 则会这样:
<custom-input
  v-bind:value="searchText"
  v-on:input="searchText = $event"
></custom-input>
为了让它正常工作,这个组件内的 <input> 必须:
value attribute 绑定到一个名叫 value 的 prop 上input 事件被触发时,将新的值通过自定义的 input 事件抛出Vue.component('custom-input', {
  props: ['value'],
  template: `
    <input
      v-bind:value="value"
      v-on:input="$emit('input', $event.target.value)"
    >
  `
})
现在 v-model 就应该可以在这个组件上完美地工作起来了
<custom-input
  v-model="searchText"
>
</custom-input>
<alert-box>
  发生了不好的事情。
</alert-box>
Vue.component('alert-box', {
  template: `
    <div class="demo-alert-box">
      <strong>Error!</strong>
      <slot></slot>
    </div>
  `
})
<div id="dynamic-component-demo" class="demo">
  <button
    v-for="tab in tabs"
    v-bind:key="tab"
    v-bind:class="['tab-button', { active: currentTab === tab }]"
    v-on:click="currentTab = tab"
  >
    {{ tab }}
  </button>
  <component v-bind:is="currentTabComponent" class="tab"></component>
</div>
<script>
  Vue.component("tab-home", {
    template: "<div>Home component</div>"
  });
  Vue.component("tab-posts", {
    template: "<div>Posts component</div>"
  });
  Vue.component("tab-archive", {
    template: "<div>Archive component</div>"
  });
  new Vue({
    el: "#dynamic-component-demo",
    data: {
      currentTab: "Home",
      tabs: ["Home", "Posts", "Archive"]
    },
    computed: {
      currentTabComponent: function() {
        return "tab-" + this.currentTab.toLowerCase();
      }
    }
  });
</script>
有些 HTML 元素,诸如 <ul>、<ol>、<table> 和 <select>,对于哪些元素可以出现在其内部是有严格限制的。有些元素,诸如 <li>、<tr> 和 <option>,只能出现在其它某些特定的元素内部
<table>
  <blog-post-row></blog-post-row>
</table>
<blog-post-row> 会被作为无效的内容提升到外部
如果我们从以下来源使用模板的话,这条限制是不存在的
template: '...').vue)<script type="text/x-template"><template>
  <button v-on:click="show = !show">
    切换
  </button>
  <transition name="fade">
    <p v-if="show">切换内容</p>
  </transition>
</template>
<script>
  export default {
    data: function() {
      return {
        show: true
      };
    }
  };
</script>
<style scoped>
  .fade-enter-active, .fade-leave-active {
    transition: opacity .5s;
  }
  /* .fade-leave-active 低于 2.1.8 版本 */
  .fade-enter, .fade-leave-to {
    opacity: 0;
  }
</style>
<template>
  <button @click="show = !show">
    切换渲染
  </button>
  <transition name="slide-fade">
    <p v-if="show">切换内容</p>
  </transition>
</template>
<script>
  export default {
    data: function() {
      return {
        show: true
      };
    }
  };
</script>
<style scoped>
  /* 可以设置不同的进入和离开动画 */
  /* 设置持续时间和动画函数 */
  .slide-fade-enter-active {
    transition: all .3s ease;
  }
  .slide-fade-leave-active {
    transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);
  }
  /* .slide-fade-leave-active 用于 2.1.8 以下版本 */ 
  .slide-fade-enter, .slide-fade-leave-to {
    transform: translateX(10px);
    opacity: 0;
  }
</style>
<template>
  <button @click="show = !show">切换展示</button>
  <transition name="bounce">
    <p v-if="show">切换内容</p>
  </transition>
</template>
<script>
  export default {
    data: function() {
      return {
        show: true
      };
    }
  };
</script>
<style scoped>
.bounce-enter-active {
  animation: bounce-in .5s;
}
.bounce-leave-active {
  animation: bounce-in .5s reverse;
}
@keyframes bounce-in {
  0% {
    transform: scale(0);
  }
  50% {
    transform: scale(1.5);
  }
  100% {
    transform: scale(1);
  }
}
</style>
| :- | :- | 
|---|---|
| v-enter | 定义进入过渡的开始状态 # | 
| v-enter-active | 定义进入过渡生效时的状态 # | 
| v-enter-to(2.1.8) | 定义进入过渡的结束状态 # | 
| v-leave | 定义离开过渡的开始状态 # | 
| v-leave-active | 定义离开过渡生效时的状态 # | 
| v-leave-to(2.1.8) | 定义离开过渡的结束状态 # | 
如果你使用了 <transition name="my-tran">,那么 v-enter 会替换为 my-tran-enter。
| :- | :- | 
|---|---|
| enter-class | # | 
| enter-active-class | # | 
| enter-to-class(2.1.8+) | # | 
| leave-class | # | 
| leave-active-class | # | 
| leave-to-class(2.1.8+) | # | 
<transition
  name="custom-classes-transition"
  enter-active-class="animated tada"
  leave-active-class="animated bounceOutRight"
>
  <p v-if="show">hello</p>
</transition>
<transition> 组件上的 duration prop 定制一个显性的过渡持续时间 (以毫秒计):
<transition :duration="1000">
  ...
</transition>
你也可以定制进入和移出的持续时间:
<transition :duration="{
  enter: 500,
  leave: 800
}">
  ...
</transition>
可以通过 appear attribute 设置节点在初始渲染的过渡
<transition appear>
  <!-- ... -->
</transition>
这里默认和进入/离开过渡一样,同样也可以自定义 CSS 类名
<transition
  appear
  appear-class="custom-appear-class"
  appear-to-class="custom-appear-to-class"
  appear-active-class="custom-appear-active-class"
>
  <!-- ... -->
</transition>
自定义 JavaScript 钩子:
<transition
  appear
  v-on:before-appear="customBeforeAppearHook"
  v-on:appear="customAppearHook"
  v-on:after-appear="customAfterAppearHook"
  v-on:appear-cancelled="customAppearCancelledHook"
>
  <!-- ... -->
</transition>
无论是 appear attribute 还是 v-on:appear 钩子都会生成初始渲染过渡
<transition
  v-on:before-enter="beforeEnter"
  v-on:enter="enter"
  v-on:after-enter="afterEnter"
  v-on:enter-cancelled="enterCancelled"
  v-on:before-leave="beforeLeave"
  v-on:leave="leave"
  v-on:after-leave="afterLeave"
  v-on:leave-cancelled="leaveCancelled"
>
  <!-- ... -->
</transition>
钩子函数可以结合 CSS transitions/animations 使用,也可以单独使用
<template>
  <button v-on:click="add">添加</button>
  <button v-on:click="remove">删除</button>
  <transition-group name="list" tag="p">
    <span v-for="item in items" v-bind:key="item" class="list-item">
      {{ item }}
    </span>
  </transition-group>
</template>
<script>
  export default {
    data: function() {
      return {
        items: [1,2,3,4,5,6,7,8,9],
        nextNum: 10
      };
    },
    methods: {
      randomIndex: function () {
        return Math.floor(Math.random() * this.items.length)
      },
      add: function () {
        this.items.splice(this.randomIndex(), 0, this.nextNum++)
      },
      remove: function () {
        this.items.splice(this.randomIndex(), 1)
      },
    }
  };
</script>
<style scoped>
  .list-item {
    display: inline-block;
    margin-right: 10px;
  }
  .list-enter-active, .list-leave-active {
    transition: all 1s;
  }
  /* .list-leave-active 适用于 2.1.8 以下版本 */
  .list-enter, .list-leave-to {
    opacity: 0;
    transform: translateY(30px);
  }
</style>
| :- | :- | 
|---|---|
| vm.$data | 观察的数据对象 # | 
| vm.$props(2.2.0) | 组件接收的 props 对象 # | 
| vm.$el | 实例使用的根 DOM 元素 # | 
| vm.$options | 实例的初始化选项 # | 
| vm.$parent | 父实例 # | 
| vm.$root | 当前组件树的根实例 # | 
| vm.$children | 当前实例的直接子组件 # | 
| vm.$slots | 访问被插槽分发的内容 # | 
| vm.$scopedSlots(2.1.0) | 访问作用域插槽 # | 
| vm.$refs | DOM 元素和组件实例 # | 
| vm.$isServer | 是否运行于服务器 # | 
| vm.$attrs(2.4.0) | 包含父作用域中不作为 prop 被识别的属性绑定 ( # | 
| vm.$listeners(2.4.0) | 包含了父作用域中的 (不含 .native 修饰器的) v-on事件监听器 # | 
| :- | :- | 
|---|---|
| v-on:click.stop# | 调用 event.stopPropagation()。 | 
| v-on:click.prevent# | 调用 event.preventDefault()。 | 
| v-on:click.capture# | 添加事件侦听器时使用 capture 模式。 | 
| v-on:click.self# | 只当事件是从侦听器绑定的元素本身触发时才触发回调。 | 
| v-on:click.{keyCode|keyAlias}# | 只当事件是从特定键触发时才触发回调。 | 
| v-on:click.native# | 监听组件根元素的原生事件。 | 
| v-on:click.once# | 只触发一次回调。 | 
| v-on:click.passive(2.3.0) # | 以 { passive: true } 模式添加侦听器 |