VUE Api
v-on:click=“”:事件监听
v-bind:href
Object.freeze() :
阻止修改现有的属性,系统无法追踪变化
v-once:
只渲染元素和组件一次
v-html:
原始HTML输出
v-bind:
动态地绑定一个或多个特性,或一个组件 prop 到表达式
可作用在HTML上,Mustache语法不能作用在HTML上
语法
(1)VUE 实例的实例属性与方法,前缀 $ 表示,区分用户定义的属性
自定义组件:
//定义名为 todo-item 的新组件
Vue.component('todo-item', {
template: '<li>这是个待办项</li>'
})
(2)修饰符 (Modifiers) 是以半角句号 . 指明的特殊后缀
//v-bin缩写
<!-- 完整语法 -->
<a v-bind:href="url">...</a>
<!-- 缩写 -->
<a :href="url">...</a>
//v-on 缩写
<!-- 完整语法 -->
<a v-on:click="doSomething">...</a>
<!-- 缩写 -->
<a @click="doSomething">...</a>
(3)使用JavaScript表达式
{{ number + 1 }}
{{ ok ? 'YES' : 'NO' }}
{{ message.split('').reverse().join('') }}
<div v-bind:id="'list-' + id"></div>
以下不会生效
<!-- 这是语句,不是表达式 -->
{{ var a = 1 }}
<!-- 流控制也不会生效,请使用三元表达式 -->
{{ if (ok) { return message } }}
(4)计算属性:处理复杂逻辑。关键字computed
<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('')
}
}
})
计算属性的 setter:计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
(5)侦听器 watch
var watchExampleVM = new Vue({
el: '#watch-example',
data: {
question: '',
answer: 'I cannot give you an answer until you ask a question!'
},
watch: {
// 如果 `question` 发生改变,这个函数就会运行
question: function (newQuestion, oldQuestion) {
this.answer = 'Waiting for you to stop typing...'
this.getAnswer()
}
}
});
(6) 绑定 HTML Class
v-bin:class
<div v-bind:class="{ active: isActive }"></div>
//传入更多属性来动态切换多个 class
<div class="static"
v-bind:class="{ active: isActive, 'text-danger': hasError }">
</div>
等价于
<div class="static active"></div>
//数组绑定class
<div v-bind:class="[activeClass, errorClass]"></div>
<div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
(7) 绑定内联样式
v-bind:style
非常像 CSS,但其实是一个 JavaScript 对象
//直接绑定到一个样式对象
<div v-bind:style="styleObject"></div>
data: {
styleObject: {
color: 'red',
fontSize: '13px'
}
}
//数组语法绑定
<div v-bind:style="[baseStyles, overridingStyles]"></div>
(8)条件渲染
//普通模板
<!-- Handlebars 模板 -->
{{#if ok}}
<h1>Yes</h1>
{{/if}}
//在VUE if
<h1 v-if="ok">Yes</h1>
//IF ELSE
<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
//在 <template> 元素上使用 v-if 条件渲染分组
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
//if else
<div v-if="Math.random() > 0.5">
Now you see me
</div>
<div v-else>
Now you don't
</div>
//if else elseif else
<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 管理可复用的元素,key标识的不复用,将被重新渲染,其他元素复用。
<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>
(9) v-if 和 v-show 区别
v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
列表渲染
(1)v-for
<ul id="example-1">
<li v-for="item in items">
{{ item.message }}
</li>
</ul>
var example1 = new Vue({
el: '#example-1',
data: {
items: [
{ message: 'Foo' },
{ message: 'Bar' }
]
}
})
//调用方式一
<li v-for="item in items">
{{ item.message }}
</li>
//调用方式二 (第二个参数为索引)
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
//调用方式三 (键值对)
<div v-for="(value, key) in object">
{{ key }}: {{ value }}
</div>
//调用方式四 (第三个参数为索引)
<div v-for="(value, key, index) in object">
{{ index }}. {{ key }}: {{ value }}
</div>
//调用方式五 (不复用,开销大)
<div v-for="item in items" :key="item.id">
<!-- 内容 -->
</div>
数组更新
(1) 变异
push()
pop()
shift()
unshift()
splice()
sort()
reverse()
错误写法
当你利用索引直接设置一个项时,例如:vm.items[indexOfItem] = newValue
当你修改数组的长度时,例如:vm.items.length = newLength
正确写法
//利用索引直接设置一个项
// Vue.set
Vue.set(example1.items, indexOfItem, newValue)
// Array.prototype.splice
example1.items.splice(indexOfItem, 1, newValue)
---------------
//修改数组的长度
example1.items.splice(newLength)
事件
事件修饰符“.”
修饰符是由点开头的指令后缀来表示的
.stop
.prevent
.capture
.self
.once
<!-- 阻止单击事件继续传播 -->
<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>
<!-- 点击事件将只会触发一次 -->
<a v-on:click.once="doThis"></a>
<!-- 只有在 `keyCode` 是 13 时调用 `vm.submit()` -->
<input v-on:keyup.13="submit">
<!-- 同上 -->
<input v-on:keyup.enter="submit">
<!-- 缩写语法 -->
<input @keyup.enter="submit">
使用修饰符时,顺序很重要;相应的代码会以同样的顺序产生。因此,用 @click.prevent.self 会阻止所有的点击,而 @click.self.prevent 只会阻止对元素自身的点击。
//全部的按键别名
.enter
.tab
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
表单
v-model
(1) 文本
<input v-model="message" placeholder="edit me">
<p>Message is: {{ message }}</p>
(2)多行文本
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br>
<textarea v-model="message" placeholder="add multiple lines"></textarea>
(3)单个复选框
<input type="checkbox" id="checkbox" v-model="checked">
<label for="checkbox">{{ checked }}</label>
(4)多个复选框绑定到同一个数组
<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: []
}
})
(5)单选按钮
<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: ''
}
})
(6)单选选择框
<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: ''
}
})
(7)多选选择框 (绑定到一个数组)
<div id="example-6">
<select v-model="selected" multiple style="width: 50px;">
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br>
<span>Selected: {{ selected }}</span>
</div>
//v-for动态渲染
<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' }
]
}
})
值绑定
在元素中添加value属性
单选框值绑定
<!-- 当选中时,`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"
>
单选按钮值绑定
<input type="radio" v-model="pick" v-bind:value="a">
选择框的选项
<select v-model="selected">
<!-- 内联对象字面量 -->
<option v-bind:value="{ number: 123 }">123</option>
</select>
修饰符
.lazy : 转变为使用 change 事件同步数据更新
<!-- 在“change”时而非“input”时更新 -->
<input v-model.lazy="msg" >
.number : 输入值转为数值类型
<input v-model.number="age" type="number">
.trim : 自动过滤用户输入的首尾空白字符
<input v-model.trim="msg">
组件使用
(1)注册全局组件 : Vue.component(tagName, options)
Vue.component('my-component', {
// 选项
})
<div id="example">
<my-component></my-component>
</div>
// 注册
Vue.component('my-component', {
template: '<div>A custom component!</div>'
})
// 创建根实例
new Vue({
el: '#example'
})
(2)局部注册
var Child = {
template: '<div>A custom component!</div>'
}
new Vue({
// ...
components: {
// <my-component> 将只在父组件模板中可用
'my-component': Child
}
})
(3)用 is 标识DOM模板解析自定义组件
以下解析失败
<table>
<my-row>...</my-row>
</table>
用 is 标识解析正确
<table>
<tr is="my-row"></tr>
</table>
(4)父组件和子组件事件传递
父子组件的关系可以总结为 prop 向下传递,事件向上传递。
使用 Prop 传递数据 : 父组件的数据需要通过 prop 才能下发到子组件
//子组件要显式地用 props 选项声明它预期的数据
Vue.component('child', {
// 声明 props
props: ['message'],
// 就像 data 一样,prop 也可以在模板中使用
// 同样也可以在 vm 实例中通过 this.message 来使用
template: '<span>{{ message }}</span>'
})
<child message="hello!"></child>
注意:
HTML 特性是不区分大小写的。所以,当使用的不是字符串模板时,camelCase (驼峰式命名) 的 prop 需要转换为相对应的 kebab-case (短横线分隔式命名):
Vue.component('child', {
// 在 JavaScript 中使用 camelCase
props: ['myMessage'],
template: '<span>{{ myMessage }}</span>'
})
<!-- 在 HTML 中使用 kebab-case -->
<child my-message="hello!"></child>
(5) 绑定对象prop传递
todo: {
text: 'Learn Vue',
isComplete: false
}
<todo-item v-bind="todo"></todo-item>
等价于
<todo-item
v-bind:text="todo.text"
v-bind:is-complete="todo.isComplete"
></todo-item>
注意
<!-- 传递了一个字符串 "1" -->
<comp some-prop="1"></comp>
<!-- 传递真正的数值 -->
<comp v-bind:some-prop="1"></comp>
(6)子组件与父组件通信
使用 $on(eventName) 监听事件
使用 $emit(eventName) 触发事件
(7)修饰符.native监听原生事件
<my-component v-on:click.native="doTheThing"></my-component>
(8)非父子组件的通信
var bus = new Vue()
// 触发组件 A 中的事件
bus.$emit('id-selected', 1)
// 在组件 B 创建的钩子中监听事件
bus.$on('id-selected', function (id) {
// ...
})
生命周期
created , mounted ,updated destroyed
插值
文本插值,使用“Mustache”语法(双大括号)。eg: Message: {{ msg }}