模板语法
文本
双大括号的文本插值
<span>Message:{{msg}}</span>
v-once指令:一次性的指令,数据改变时,插值处的内容不会改变。
<span v-once>Message:{{msg}}</span>
v-html指令:双括号会将数据解释为文本,v-html输出真正的HTML。
<span v-html="rawHtml"></span></p>
注意
你的站点上动态渲染的任意 HTML 可能会非常危险,因为它很容易导致 XSS 攻击。
请只对可信内容使用 HTML 插值,绝不要对用户提供的内容使用插值。
属性
v-bind指令:代表属性,在布尔特性的情况下,它的存在即暗示为 true。
<div v-bind:id="dynamicId"></div>
使用JavaScript表达式
对于所有的数据绑定,Vue.js 都提供了完全的 JavaScript 表达式支持。
{{number+1}}
{{ok? 'yes':'no'}}
{{ message.split('').reverse().join('')}}
<div v-bind:id="'list-' + id"></div>
注意
只能访问全局变量的一个白名单,如 Math 和 Date。
不该在模板表达式中试图访问用户定义的全局变量。
指令
带有 v- 前缀的特殊特性。指令特性的值预期是单个 JavaScript 表达式 (v-for 是例外情况)。指令的职责是,当表达式的值改变时,将其产生的连带影响,响应式地作用于 DOM。
<p v-if="seen">现在你看到我了</p>
v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素。
v-modal指令,实现表单输入和应用状态之间的双向绑定
<input v-modal="message"/>
<script>
new Vue({
el:#app,
data:{
message:'hello',
}
})
</script>
参数
一些指令能够接受一些参数,在指令名称之后,用冒号表示。
<a v-bind:href="url"></a>
<a v-on:click="dosomething"></a>
动态参数
用方括号括起来的 JavaScript 表达式作为一个指令的参数。
<a v-bind:[attributeName]="url"> ... </a>
这里的 attributeName 会被作为一个 JavaScript 表达式进行动态求值,求得的值将会作为最终的参数来使用。例如,如果你的 Vue 实例有一个 data 属性 attributeName,其值为 "href",那么这个绑定将等价于 v-bind:href。
使用动态参数为一个动态的事件名绑定处理函数。
<a v-on:[eventName]="doSomething"> ... </a>
同样地,当 eventName 的值为 "focus" 时,v-on:[eventName] 将等价于 v-on:focus.
修饰符
修饰符 (modifier) 是以半角句号 . 指明的特殊后缀,用于指出一个指令应该以特殊方式绑定。例如,.prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault():
<form v-on:submit.prevent="onSubmit">...</form>
缩写
v-bind缩写
<a :href="url">...</a>
v-on缩写
<a @click="doSomething">...</a>
计算属性和侦听器
计算属性
对于任何复杂逻辑,你都应当使用计算属性。
<div id="example">
<p>Original message: "{{ message }}"</p>
<p>Computed reversed message: "{{ reversedMessage }}"</p>
</div>
var vm = new Vue({
el: '#example',
data: {
message: 'Hello'
},
computed: {
// 计算属性的 getter
reversedMessage: function () {
// `this` 指向 vm 实例
return this.message.split('').reverse().join('')
}
}
})
侦听器
通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。
<div id="watch-example">
<input v-modal="question"/>
{{answer}}
</div>
<script>
var watchExampleVM = new Vue({
el:#id="watch-example",
data:{
question:'',
answer:'I cannot give you an answer until you ask a question!',
},
watch:{
question:function(newQuestion, oldQuestion){//当question发生改变,调用这个函数。
this.answer = 'Waiting for you to stop typing...'
this.debouncedGetAnswer()
}
},
created:function(){
this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
}
methods: {
getAnswer: function () {
if (this.question.indexOf('?') === -1) {
this.answer = 'Questions usually contain a question mark. ;-)'
return
}
this.answer = 'Thinking...'
var vm = this
axios.get('https://yesno.wtf/api')
.then(function (response) {
vm.answer = _.capitalize(response.data.answer)
})
.catch(function (error) {
vm.answer = 'Error! Could not reach the API. ' + error
})
}
}
})
</script>
class与style绑定
对象语法
当isActive或者hasError变化时,class列表也会相应的进行更新。
<div
class="static" v-bind:class="{active:isActive,'text-danger':hasError}"
></div>
data:{
isActive:true,
hasError:false,
}
绑定的对象不必内联定义在模板里。
<div class="classObject"></div>
data:{
classObject:{
active:true,
'text-danger':false
}
}
同样可以绑定对象的计算属性
<div class="classObject"></div>
data:{
isActive:true,
error:null
},
computed:{
classObject:function(){
return {
active:this.isActive && !this.error,
'text-danger':this.error && this.error.type === 'fatal'
}
}
}
数组语法
<div v-bind:class="[activeClass, errorClass]"></div>
data:{
activeClass: 'active',
errorClass: 'text-danger'
}
根据条件切换列表中的class,可以用三元表达式。
<div v-bind:class="[isActive? activeClass:'',errorClass]"></div>
在数组语法中,使用对象语法
<div v-bind:class="[{active:isActive},errorClass]"></div>
绑定内联样式
对象语法
v-bind:style,CSS 属性名可以用驼峰式 (camelCase) 或短横线分隔 (kebab-case,记得用单引号括起来) 来命名:
<div v-bind:style="{color:activeColor,fontSize:fontSize +'px'}"></div>
data:{
activeColor:'red',
fontSize:30
}
直接绑定到样式对象
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
数组语法
v-bind:style 的数组语法可以将多个样式对象应用到同一个元素上
<div v-bind:style="[baseStyles, overridingStyles]"></div>
多重值
为 style 绑定中的属性提供一个包含多个值的数组,常用于提供多个带前缀的值,例如:
<div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
这样写只会渲染数组中最后一个被浏览器支持的值。
在本例中,如果浏览器支持不带浏览器前缀的 flexbox,那么就只会渲染 display: flex。
条件渲染
v-if,v-else
v-if用于条件性的渲染一块内容。这块内容,只有在指令的表达式返回truthy值的时候被渲染,也可以用v-else添加一个else块。
<h1 v-if="awesome">good</h1>
<h1 v-else>bad</h1>
在 <template> 元素上使用 v-if 条件渲染分组
因为 v-if 是一个指令,所以必须将它添加到一个元素上。但是如果想切换多个元素呢?此时可以把一个 template 元素当做不可见的包裹元素,并在上面使用 v-if。最终的渲染结果将不包含 template 元素。
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
v-else-if
充当 v-if 的“else-if 块”,可以连续使用,v-else-if 也必须紧跟在带 v-if 或者 v-else-if 的元素之后.
<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>
用 key 管理可复用的元素
input 是两个独立的元素,不复用,label会被复用。
<template v-if="loginType === 'username'">
<label>Username</label>
<input placeholder="Enter your username" key="username-input">
</template>
<template v-else>
<label>Email</label>
<input placeholder="Enter your email address" key="email-input">
</template>
v-show
另一个用于根据条件展示元素的选项,不同的是带有 v-show 的元素始终会被渲染并保留在 DOM 中。v-show 只是简单地切换元素的 CSS 属性 display。
<h1 v-show="ok">ok</h1>
注意,v-show 不支持 template 元素,也不支持 v-else。
列表渲染
v-for把一个数组对应为一组元素,也可以用 of 替代 in 作为分隔符
<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' }
]
}
})
一个对象的 v-for
<ul id="v-for-object" class="demo">
<li v-for="value in object">
{{ index }}. {{ key }}: {{ value }}
</li>
</ul>
new Vue({
el: '#v-for-object',
data: {
object: {
firstName: 'John',
lastName: 'Doe',
age: 30
}
}
})
key
为了给 Vue 一个提示,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素,你需要为每项提供一个唯一 key 属性。理想的 key 值是每项都有的唯一 id。
<div v-for="item in items" v-bind:key="item.id">
<!-- 内容 -->
</div>
变异方法
push() 向数组的末尾添加一个或多个元素,并返回新的长度
pop() 删除并返回数组的最后一个元素
shift() 把数组的第一个元素从其中删除,并返回第一个元素的值
unshift() 向数组的开头添加一个或更多元素,并返回新的长度
splice() 从数组中添加/删除项目,然后返回被删除的项目
sort() 对数组的元素进行排序
reserve() 颠倒数组中元素的顺序
会改变被这些方法调用的原始数组。相比之下,也有非变异 (non-mutating method) 方法,例如:filter(), concat() 和 slice() 。这些不会改变原始数组,但总是返回一个新数组。当使用非变异方法时,可以用新数组替换旧数组:
example1.items = example1.items.filter(function (item) {
return item.message.match(/Foo/)
})
替换数组
filter() 创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
concat() 连接两个或多个数组
slice() 从已有的数组中返回选定的元素
split() 方法用于把一个字符串分割成字符串数组
注意事项
由于 JavaScript 的限制,Vue 不能检测以下变动的数组
当你利用索引直接设置一个项时
当你修改数组的长度时
var vm = new Vue({
data: {
items: ['a', 'b', 'c']
}
})
解决办法
Vue.set(vm.items, indexOfItem, newValue)||vm.$set()
vm.items.splice(newLength)
对象更改检测注意事项
Vue 不能检测对象属性的添加或删除,对于已经创建的实例,Vue 不能动态添加根级别的响应式属性。但是,可以使用 Vue.set(object, key, value) 方法向嵌套对象添加响应式属性。例如:
var vm = new Vue({
data: {
userProfile: {
name: 'Anika'
}
}
})
Vue.set(vm.UserProfile,'age',27)||vm.$set()
有时你可能需要为已有对象赋予多个新属性,比如使用 Object.assign() 或 _.extend()
vm.userProfile=Object.assign({},vm.userProfile,{
age:27,
favouriteColor:'pink'
})
显示过滤/排序结果
创建返回过滤或排序数组的计算属性
<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 循环中) 你可以使用一个 method 方法:
<li v-for:"n in even(numbers)">{{n}}</li>
data:{
numbers:[1,2,3,4,5]
},
methods:{
even:function(numbers){
return this.numbers.filter(function(number){
return number%2===0;
})
}
}
一段取值范围的v-for
v-for 也可以取整数。在这种情况下,它将重复多次模板
<div v-for="n in 10">{{n}}</div> 1,2,3,4,5,6,7,8,9,10
v-for on a template
<ul>
<template v-for="item in items">
<li>{{ item.msg }}</li>
<li class="divider" role="presentation"></li>
</template>
</ul>
v-for with v-if 注意
不推荐同时使用 v-if 和 v-for
当它们处于同一节点,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-for
2.2.0+ 的版本里,当在组件中使用 v-for 时,key 现在是必须的
<my-component
v-for="(item,index) in items"
v-bind:index="index"
v-bind:item="item"
v-bind:key="item.id"
>
</my-component>
事件处理
监听事件
可以用 v-on 指令监听 DOM 事件,并在触发时运行一些 JavaScript 代码。
<div id="example1">
<button v-on:click="counter+=1">Add 1</button>
<p>{{counter}}</p>
</div>
事件处理方法
v-on 还可以接收一个需要调用的方法名称
<button v-on:click="greet">Greet</button>
data: {
name: 'Vue.js'
},
methods: {
greet: function (event) {
alert('Hello ' + this.name + '!')
if (event) {
alert(event.target.tagName)
}
}
}
内联处理器中的方法
除了直接绑定到一个方法,也可以在内联 JavaScript 语句中调用方法:
<button v-on:click="say('hi')">Say hi</button>
methods: {
say: function (message) {
alert(message)
}
}
有时也需要在内联语句处理器中访问原始的 DOM 事件。可以用特殊变量 $event 把它传入方法:
<button v-on:click="warn('Form cannot be submitted yet.', $event)">
Submit
</button>
methods: {
warn: function (message, event) {
if (event) event.preventDefault()
alert(message)
}
}
事件修饰符(待补充)
.stop
.prevent
.capture
.self
.once
.passive
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>
<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></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>
注意
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。v-on:click.prevent.self 会阻止所有的点击。v-on:click.self.prevent 只会阻止对元素自身的点击。
按键修饰符
Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` -->
<input v-on:keyup.enter="submit">
按键码
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
你还可以通过全局 config.keyCodes 对象自定义按键修饰符别名:
// 可以使用 `v-on:keyup.f1`
Vue.config.keyCodes.f1 = 112
表单输入绑定
基础用法
用 v-model 指令在表单 input、textarea 及 select 元素上创建双向数据绑定。它会根据控件类型自动选取正确的方法来更新元素。
v-model 在内部使用不同的属性为不同的输入元素并抛出不同的事件:
text 和 textarea 元素使用 value 属性和 input 事件;
checkbox 和 radio 使用 checked 属性和 change 事件;
select 字段将 value 作为 prop 并将 change 作为事件。
文本、多行文本
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
在文本区域插值 (<textarea>{{text}}</textarea>) 并不会生效,应用 v-model 来代替。
复选框
当个复选框,绑定到布尔值
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
多个复选框,绑定到同一数组
<div id='example-3'>
<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>
</div>
new Vue({
el: '#example-3',
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>
<br>
<span>Picked: {{ picked }}</span>
</div>
new Vue({
el: '#example-4',
data: {
picked: ''
}
})
下拉框
单选时
<div id="example-5">
<select v-model="selected">
<option disabled value="">请选择</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
new Vue({
el: '...',
data: {
selected: ''
}
})
多选时绑定到一个数组
用 v-for 渲染的动态选项:
<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' }
]
}
})
值绑定
对于单选按钮,复选框及选择框的选项,v-model 绑定的值通常是静态字符串 (对于复选框也可以是布尔值):
<!-- 当选中时,`picked` 为字符串 "a" -->
<input type="radio" v-model="picked" 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="checkbox"
v-model="toggle"
true-value="yes"
false-value="no"
>
// 当选中时
vm.toggle === 'yes'
// 当没有选中时
vm.toggle === 'no'
单选按钮
<input type="radio" v-model="pick" v-bind:value="a">
// 当选中时
vm.pick === vm.a