主要内容
- 模板语法(文本插值、属性绑定、JS表达式、过滤器、指令)
- Vue实例(viewModal(属性+函数)、生命周期)
- 计算属性和监听器 (computed(get,set) 与 watch)
- 样式绑定(对象绑定、数组绑定、内联绑定)
- 条件绑定(v-if v-show)
- 列表渲染 (v-for、:key、数组监测、过滤/排序)
- 事件处理 (监听、修饰符、key修饰符)
- 表单输入绑定(text、checkbox、radio、select)
模板语法
文本插值
- 使用 `
{{ }}
/ <span v-text="msg"></span>` 绑定数据
- `
{{ }}
` 纯文本绑定,单向,随vm变化而变化
- `
<span v-once>
{{ msg }}
</span>` 纯文本,单次,不跟随vm变化
- `
<span v-html="msg">
</span>` 不转义html标签,绑定html
|
属性绑定
- 使用 `
v-bind` 指令绑定数据至标签属性
- `
<a v-bind:id="msgId"></a> 简写 <a :id="msgId"></a>`
|
模板中的JS
- 支持表达式执行,但不支持多个表达式、语句和控制流的执行
- 属性绑定和
绑定的数据都支持JS表达式
//加减乘除、三元运算、方法调用
{{ number + 1 }
}
{{ ok ? 'YES' : 'NO' }
}
{{ message.split('').reverse().join('') }
}
<div v-bind:id="'list-' + id">
</div>
//错误用法
{{ var a = 1 }
}
{{ if (ok) { return message }
}}
|
过滤器
-
使用 `|` 对原始值进行处理
-
用于属性绑定与 `{{ }}`
-
`{{ msg | capitalize }} <a :id="msgId | formatId"></a>`
-
可以串联 `{{ msg | filterA | filterB }}`
-
可以接收参数 `{{ msg | filterA(arg1, arg2) }}`
|
指令
- 带有 `
v-` 前缀的特殊属性
- 当其表达式的值改变时相应地将某些行为应用到 DOM 上
- `
v-bind/v-for/v-html/v-on/v-if/...`
- `
v-bind` 缩写 `
<a v-bind:href="url"></a><a :href="url"></a>`
- `
v-on` 缩写 `
<a v-on:click="doSomething"></a><a @click="doSomething"></a>`
|
注册过滤器
Vue.filters(
'capitalize',value=>{
if (!value)
return
''
value = value.toString()
return value.charAt(
0).toUpperCase() + value.slice(
1)
})
filters: {
capitalize:
function (value, arg1) {
if (!value)
return
''
value = value.toString()
return value.charAt(
0).toUpperCase() + value.slice(
1)
}
}
<span>{{msg | capitalize(arg1) }}
|
注意
- 注册过滤器时,如果需要传递参数,必须从第二个参数开始,第一个参数为当前绑定的数据
- 过滤器一般用于简单的文本格式化,如果是对多个状态数据,或是复杂的数据处理应该使用计算属性
注册指令
Vue.directive(
'focus', {
inserted:
function (el) {
el.focus()
}
})
directives: {
focus: {
}
}
<input v-focus />
|
Vue实例
Vue 实例,实则也就是 ViewModel
(数据 + 函数),都是通过构造函数 Vue 创建
var vm =
new Vue({
name:
'root',
data: {
a:
1 } /
Function,
props:[]/{},
computed:{},
watch:{},
methods:{},
directives:{},
filters:{},
components:{},
beforeCreate(){
console.log(
'beforeCreate ==> 实例创建')
},
created(){
console.log(
'created ==> 实例创建完成,属性已绑定')
},
beforeMount(){
console.log(
'beforeMount ==> 模板编译/挂载之前')
},
mounted(){
console.log(
'mounted ==> 模板编译/挂载之后')
},
beforeUpdate(){
console.log(
'beforeUpdate ==> 组件更新之前')
},
updated(){
console.log(
'updated ==> 组件更新之后')
},
activated(){
console.log(
'activated ==> 组件被激活时(for keep-alive组件)')
},
deactivated(){
console.log(
'deactivated ==> 组件被移除时(for keep-alive组件)')
},
beforeDestroy(){
console.log(
'beforeDestroy ==> 组件销毁之前')
},
destroyed(){
console.log(
'destroyed ==> 组件销毁之后')
}
})
|
计算属性与监听器
computed
- 任何复杂逻辑,都应当使用计算属性
- 可以像绑定普通属性一样在模板中绑定计算属性
- 声明式地创建依赖关系,计算属性的 getter 是干净无副作用的,因此也是易于测试和理解的。
<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: {
// a computed getter
reversedMessage: function () {
// `this` points to the vm instance
return this.message.split('').reverse().join('')
}
}
})
|
使用 methods
和 filter
也能达到计算属性同样的效果,但计算属性使模板更加简单清晰(模板中放入太多的逻辑会让模板过重且难以维护)。
计算属性有 计算缓存 的特性,计算属性是基于它的依赖缓存,只有在它的相关依赖发生改变时才会重新取值,而 methods
每次执行都会重新取值。
什么需要缓存?
假设我们有一个重要的计算属性 A ,这个计算属性需要一个巨大的数组遍历和做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter !如果你不希望有缓存,请用 method 替代。
getter与setter
计算属性默认为 getter
data: {
firstName:
'Foo',
lastName:
'Bar'
},
computed: {
fullName:
function () {
return
this.firstName +
' ' +
this.lastName
}
}
|
也可以添加 setter
computed: {
fullName: {
get:
function () {
return
this.firstName +
' ' +
this.lastName
},
set:
function (newValue) {
var names = newValue.split(
' ')
this.firstName = names[
0]
this.lastName = names[names.length -
1]
}
}
}
|
watch
使用 watch
来监听data,实时响应数据的变化
例:监听用户输入,显示 正在输入...
,输入完成时,显示 请稍等...
,并发送异步请求,请求成功里,显示答案
var watchExampleVM =
new Vue({
el:
'#watch-example',
data: {
question:
'',
answer:
'I cannot give you an answer until you ask a question!'
},
watch: {
question:
function (newQuestion) {
this.answer =
'正在输入...'
this.getAnswer()
}
},
methods: {
getAnswer: _.debounce(
function () {
if (
this.question.indexOf(
'?') ===
-1) {
this.answer =
'需要一个问题标识\'?\''
return
}
this.answer =
'请稍候...'
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
})
},
500
)
}
})
|
使用 watch
选项允许我们执行异步操作(访问一个 API),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这是计算属性无法做到的。
样式绑定
使用 v-bind:class
与 v-bind:style
来绑定样式
data:
()=>{
return {
isActive:
true,
hasError:
false,
classObj:{
'active':
true,
'align-left':
true,
},
activeClass:
'active',
errorClass:
'text-danger',
styleObj:{
color:
'red',
fontSize:
'13px'
},
activeColor:
'red',
fontSize:
30,
baseStyles:{
color:
'red'},
overridingStyles: {
fontSize:
'20px'}
}
}
|
对象语法绑定
class 绑定的是对象的 key,如果对象的值为 true
,则绑定 key
style 绑定的整个 对象
绑定 class
<div v-bind:
class=
"classObj">
</div>
<div
class=
"static" v-bind:
class=
"{ active: isActive, 'text-danger': hasError }">
</div>
|
绑定style
<div v-bind:style=
"{ color: activeColor, fontSize: fontSize + 'px' }">
</div>
<div v-bind:style=
"styleObj">
</div>
|
数组语法绑定
class 绑定的是数组的 值
style 绑定的是数组中的 对象
<div v-bind:
class=
"[activeClass, errorClass]">
<div v-bind:
class=
"[isActive ? activeClass : '', errorClass]">
<div v-bind:
class=
"[{ active: isActive }, errorClass]">
<div v-bind:style=
"[baseStyles, overridingStyles]">
|
条件渲染
v-if
切换元素的隐藏和显示 v-if
、v-else
、v-if-else
切换单个元素
<h1 v-if="ok">Yes</h1>
<h1 v-else>No</h1>
|
切换多个元素
<template v-if="ok">
<h1>Title</h1>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</template>
|
多条件判断
<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
值
<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
- 用于切换元素样式属性
display
的 block
和 none
- 与
v-if
不同的是,元素隐藏时,并没有从DOM中删除,而 v-if
是删除了元素保存在缓存中。
注意 v-show
不支持 <template>
语法
v-if
是真实的条件渲染,因为它会确保条件块在切换当中适当地销毁与重建条件块内的事件监听器和子组件。
v-if
也是惰性的:如果在初始渲染时条件为假,则什么也不做——在条件第一次变为真时才开始局部编译(编译会被缓存起来)。
区分 v-if
与 v-show
的使用场景:
v-if
有更高的切换消耗而 v-show
有更高的初始渲染消耗- 如果需要频繁切换使用
v-show
较好 - 如果在运行时条件不大可能改变则使用
v-if
较好
列表渲染
v-for='item of items / item in items'
用于迭代对象或数组中的元素
data: {
items: [
{
message:
'Foo' },
{
message:
'Bar' }
]
object: {
firstName:
'John',
lastName:
'Doe',
age:
30
}
}
|
基本用法
<ul id=
"example-1">
<li v-for="item in items">
{{ item.message }}
</li>
<
/ul>
|
添加第二个参数可以获取当前迭代的 key
值
数组迭代
<ul id=
"example-2">
<li v-for="(item, index) in items">
{{ parentMessage }} - {{ index }} - {{ item.message }}
</li>
<
/ul>
|
对象迭代
<div v-
for=
"(value, key) in object">
{{ key }} : {{ value }}
<
/div>
|
循环组件,向组件中传递数据
<my-component
v-
for=
"(item, index) in items"
v-bind:item=
"item"
v-bind:index=
"index">
</my-component>
|
组件有自己的作用域,向组件中传递数据需要使用属性传递
v-for
具有比 v-if
更高的优先级
判断每一个todo项是否可显示
<li v-
for=
"todo in todos" v-
if=
"!todo.isComplete">
{{ todo }}
<
/li>
|
判断是否需要迭代todos
<ul v-
if=
"shouldRenderTodos">
<li v-for="todo in todos">
{{ todo }}
</li>
<
/ul>
|
添加 key
属性
提升重复渲染效率
<div v-
for=
"item in items" :key=
"item.id">
</div>
|
数组监测
Vue重写了数组的变异方法,用于监测数组的更新
push()
、pop()
、shift()
、unshift()
、
splice()
、sort()
、reverse()
- 这些操作会改变原有数组,为变异方法
- 非变异方法返回新的数组,可以用于替换旧的数组
直接修改数组长度、利用索引修改数组的值,不会被监听到
过滤/排序
使用计算属性对原有数组进行过滤和排序
data: {
numbers: [
1,
2,
3,
4,
5 ]
},
computed: {
evenNumbers:
function () {
return
this.numbers.filter(
function (number) {
return number %
2 ===
0
})
}
}
|
事件监听
v-on
v-on
用于监听绑定的事件
<div id="example-3">
<button @click="say('hi')">Say hi</button>
<button @click="say('what')">Say what</button>
</div>
new Vue({
el: '#example-3',
methods: {
say: function (message) {
alert(message)
}
}
})
|
原生事件对象
使用 $event
传递原生事件对象
<button v-on:click="warn('hello', $event)">Submit</button>
methods: {
warn: function (message, event) {
// 现在我们可以访问原生事件对象
if (event) event.preventDefault()
alert(message)
}
}
|
事件修饰符
methods
应该只处理纯粹的数据逻辑,而不是去处理 DOM 事件细节
.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>
<!-- 只当事件在该元素本身(而不是子元素)触发时触发回调 -->
<div v-on:click.self="doThat">...</div>
<!-- 点击事件将只会触发一次
2.1
.4-->
<a v-on:click.once="doThis"></a>
<!-- 组件中的原生事件 -->
<my-component @click.native="onClick"></my-component>
|
按键修饰符
监听键盘按下的键值
监听keyCode
<!-- 只有在 keyCode 是
13 时调用 vm.submit() -->
<input v-on:keyup.13="submit">
|
常用按键别名
.enter
.tab
.delete (捕获 “删除” 和 “退格” 键)
.esc
.space
.up
.down
.left
.right
2.1
.0
.ctrl
.alt
.shift
.meta
|
<!-- 同上 -->
<input v-on:keyup.enter="submit">
|
按键组合
<!-- Alt + C -->
<input @keyup.alt.67="clear">
|
- 所有的 Vue.js 事件处理方法和表达式都严格绑定在当前视图的 ViewModel 上
- 当一个 ViewModel 被销毁时,所有的事件处理器都会自动被删除。你无须担心如何自己清理它们。
表单输入绑定
使用 v-modal
给表单控件绑定相关数据(双向绑定)
v-modal
是一个语法糖
<input v-model=
"something">
<input v-bind:value=
"something" v-on:input=
"something = $event.target.value">
|
基本输入
<input v-model=
"message" placeholder=
"edit me">
<textarea v-model=
"message" placeholder=
"add multiple lines">
</textarea>
<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>
<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>
// 下拉框
// 单选 (返回选中的值)
<select v-model="selected">
<option>A
</option>
<option>B
</option>
<option>C
</option>
</select>
// 多选(返回一个数组 ['A','B'])
<select v-model="selected" multiple>
<option>A
</option>
<option>B
</option>
<option>C
</option>
</select>
|
当有选项有 value
属性时,选中时,返回 value
, 当属性没有 value
时,选中时返回字符串或true/false
<select v-model=
"selected">
<option v-for="option in options" v-bind:value="option.value">
{{ option.text }}
</option>
<
/select>
|
绑定动态的value
v-model 绑定的 value 通常是静态字符串,对于 radio
、checkbox
、select
,可以动态的使用v-bind
设置value
<input
type=
"checkbox"
v-model=
"toggle"
v-bind:
true-value=
"a"
v-bind:
false-value=
"b"
>
vm.toggle === vm.a
vm.toggle === vm.b
|
修饰符
v-modal
的修饰符 .lazy
、 .number
、.trim
<!-- 在
"change" 而不是
"input" 事件中更新 -->
<input v-model.lazy="msg" >
// 自动将用户的输入值转为 Number 类型(如果原值的转换结果为 NaN 则返回原值)
<input v-model.number="age" type="number">
// 过滤用户输入的首尾空格
<input v-model.trim="msg">
|
自定义输入组件
使用 v-modal
自定义输入组件
前提条件,组件必须有 value
属性, 在有新的value时,可通过 input
事件获取更新的值。
自定义的货币输入组件
<currency-input v-model=
"price"></currency-input>
Vue.component('currency-input', {
template: '
<span>
$
<input
ref="input"
v-bind:value="value"
v-on:input="updateValue($event.target.value)"
>
</span>
',
props: ['value'],
methods: {
// 不是直接更新值,而是使用此方法来对输入值进行格式化和位数限制
updateValue: function (value) {
var formattedValue = value
// 删除两侧的空格符
.trim()
// 保留 2 小数位
.slice(0, value.indexOf('.') + 3)
// 如果值不统一,手动覆盖以保持一致
if (formattedValue !== value) {
this.$refs.input.value = formattedValue
}
// 通过 input 事件发出数值
this.$emit('input', Number(formattedValue))
}
}
})
http://coderlt.coding.me/2017/03/06/vue-base-01/?utm_source=tuicool&utm_medium=referral
|