渐进式 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: {// 计算属性的 getterreversedMessage: 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
<divclass="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"><liv-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 VueJane Doe2016-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>
<liv-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-componentv-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: {// 计算属性的 getterreversedMessage: 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 () { // getterreturn this.firstName + ' ' + this.lastName},set: function (newValue) { // settervar 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><textareav-model="message"placeholder="添加多行"></textarea><p>{{ message }}</p>
<inputtype="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"><optionv-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>
<inputtype="radio"v-model="pick"v-bind:value="a">
当选中时
vm.pick === vm.a
<inputtype="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-postv-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><buttonv-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
的第二个参数来提供这个值
<buttonv-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">
等价于
<inputv-bind:value="searchText"v-on:input="searchText = $event.target.value">
当用在组件上时,v-model 则会这样:
<custom-inputv-bind:value="searchText"v-on:input="searchText = $event"></custom-input>
为了让它正常工作,这个组件内的 <input> 必须:
value
attribute 绑定到一个名叫 value
的 prop
上input
事件被触发时,将新的值通过自定义的 input
事件抛出Vue.component('custom-input', {props: ['value'],template: `<inputv-bind:value="value"v-on:input="$emit('input', $event.target.value)">`})
现在 v-model
就应该可以在这个组件上完美地工作起来了
<custom-inputv-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"><buttonv-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>
如果你使用了 <transition name="my-tran">
,那么 v-enter
会替换为 my-tran-enter
。
<transitionname="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 类名
<transitionappearappear-class="custom-appear-class"appear-to-class="custom-appear-to-class"appear-active-class="custom-appear-active-class"><!-- ... --></transition>
自定义 JavaScript 钩子:
<transitionappearv-on:before-appear="customBeforeAppearHook"v-on:appear="customAppearHook"v-on:after-appear="customAfterAppearHook"v-on:appear-cancelled="customAppearCancelledHook"><!-- ... --></transition>
无论是 appear
attribute 还是 v-on:appear
钩子都会生成初始渲染过渡
<transitionv-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 } 模式添加侦听器 |
在 (2.2.0) 中新增