第1章 Vue.js基础
为什么选择Vue.js
- 框架有利于代码的维护
jQuery
对比Vue
安装和设置
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
- 不能在
body
元素上进行初始化。 - 创建一个
Vue
的实例,并将该实例的el
属性指向div
元素
vue-loader和webpack
vue-loader
是一个webpack
的加载器,允许你将一个组件的所有HTML、JavaScript
和CSS
代码编写到同一个文件中。webpack
安装xxxxxxxxxx
npm install --global vue-cli
vue init webpack
模板(Template)、数据(Data)和指令(Directive)
Vue
的核心是将数据显示在页面上
根据不同时间显示不同问候
xxxxxxxxxx
<!-- HTML结构 -->
<div id="app">
<p v-if="isMorning">早上好!</p>
<p v-if="isAfternoon">中午好!</p>
<p v-if="isEvening">晚上好!</p>
</div>
<script>
let hours = new Date().getHours()
/* 创建vue实例 */
let app = new Vue({
//el:挂载点
el: '#app',
//data: 要渲染的数据
data: {
isMorning: hours < 12,
isAfternoon: hours >= 12 && hours < 18,
isEvening: hours >= 18
}
})
</script>
- 设有
v-if
属性的元素只有传递给指令的值为真时才会显示,否则,该元素不会被写入页面。 Vue
支持在v-if
中进行简单的表达式运算
xxxxxxxxxx
<!-- HTML结构 -->
<div id="app">
<p v-if="hours < 12">早上好!</p>
<p v-if="hours >= 12 && hours < 18">中午好!</p>
<p v-if="hours >= 18">晚上好!</p>
</div>
<script>
/* 创建vue实例 */
let app = new Vue({
//el:挂载点
el: '#app',
//data: 要渲染的数据
data: {
hours:new Date().getHours()
}
})
</script>
- 在
JavaScript
中实现业务逻辑,而在template
中实现视图逻辑。 - 除了使用指令,也可以通过插值的方式将数据传递给模板。
xxxxxxxxxx
<!-- HTML结构 -->
<div id="app">
{{msg}}
</div>
<script>
/* 创建vue实例 */
let app = new Vue({
//el:挂载点
el: '#app',
//data: 要渲染的数据
data: {
mgs:'Hello,World'
}
})
</script>
获取路径且进行判断
x<!-- HTML结构 -->
<div id="app">
<p v-if="path === '/'">位于首页中</p>
<p v-else>你正位于{{path}}</p>
</div>
<script>
/* 创建vue实例 */
new Vue({
//el:挂载点
el: '#app',
//data: 要渲染的数据
data: {
path: location.pathname
}
})
</script>
location.pathname
是当前页面URL
的路径值v-else
的表现和一个if-else
语句中的else
语句一样
在模板中执行简单的表达式运算
xxxxxxxxxx
<div id="app">
<p>你备胎的名字叫做{{dogs[1]}}</p>
<p>所有的备胎的名字是{{dogs}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
dogs:['小明','小强','小刚',]
}
})
</script>
//你备胎的名字叫做小强
//所有的备胎的名字是[ "小明", "小强", "小刚" ]
v-if vs v-show
如果
v-if
指令的值为假,那么这个元素不会被插入DOM
。xxxxxxxxxx
<div v-if="true">1</div>
<div v-if="false">2</div>
和
v-show
指令比较一下,该指令使用CSS
样式控制元素的显示/隐藏。xxxxxxxxxx
<div v-show="true">1</div>
<div v-show="false">2</div>
隐藏尚未加载的内容时,
v-if
指令更好一些。xxxxxxxxxx
<div id="app">
<div v-show="user">
<p>用户名:{{user.name}}</p>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
user: undefined
}
})
</script>
// 判处异常:'name' of undefined"
--------------分割线--------------
<div id="app">
<div v-if="user">
<p>用户名:{{user.name}}</p>
</div>
</div>
<script>
new Vue({
el: '#app',
data: {
user: undefined
}
})
</script>
//没报错,直接隐藏了。
使用
v-if
会有性能开销。每次插入或者移除元素时都必须要生成元素内部的DOM
树,这在某些时候是非常大的工作量。而v-show
除了在初始创建开销时之外没有额外的开销。如果希望频繁地切换某些内容,那么v-show
会是最好的选择
模板中的循环
v-for
,这个指令通过遍历一个数组或者对象,将指令所在的元素循环输出到页面上xxxxxxxxxx
<div id="app">
<ul>
<li v-for="dog in dogs">{{dog}}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
dogs: ['小明', '小强', '小刚']
}
})
</script>
v-for
指令同样支持对象的遍历。xxxxxxxxxx
<div id="app">
<ul>
<li v-for="(item,index) in Rmb">
{{index}}的平均租金是¥{{item}}
</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
Rmb: {
东莞: '500',
广州: '1000',
深圳: '2000'
}
}
})
</script>
请记住参数的顺序是:
(value, key)
。计数器(渲染假数据可以用此方法)
xxxxxxxxxx
<div id="app">
<ul>
<li v-for="n in 10">{{n}}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
})
</script>
属性绑定
v-bind
指令用于将一个值绑定到一个HTML
属性上。简写直接用
:
亦可。xxxxxxxxxx
<div id="app">
<button :disabled="buttonDisabled">我是按钮</button>
</div>
<script>
new Vue({
el: '#app',
data:{
buttonDisabled: true
}
})
</script>
响应式
使用
setInterval
每隔一秒将这个变量递增1。xxxxxxxxxx
<div id="app">
<p>距离你上次撸管,已经过了{{seconds}}秒</p>
</div>
<script>
new Vue({
el: '#app',
data: {
seconds: 0
},
created () {
setInterval(() => {
this.seconds++
}, 1000)
}
})
</script>
created
函数方法会在应用初始化完成后执行。this.seconds
直接指向data
对象中的相应值Vue
的响应式能力除了在使用插值将数据输出到页面上时有效,在将data
对象的属性作为指令值时也同样有效。按钮隔秒禁止与显示
xxxxxxxxxx
<div id="app">
<button :disabled="buttonDisabled">自动点了{{num}}次</button>
</div>
<script>
new Vue({
el: '#app',
data: {
buttonDisabled: true,
num: 0
},
created () {
setInterval(() => {
this.buttonDisabled = !this.buttonDisabled
this.num++
}, 1000)
}
})
</script>
响应式如何实现
Vue
修改了每个添加到data上的对象,当该对象发生变化时Vue
会收到通知,从而实现响应式。
为对象添加新的属性
Vue
实例初始化,已经存在的属性是响应式的。
非响应式
xxxxxxxxxx
<div id="app">
{{formData.username}} {{formData.name}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
formData: {
username: '隔壁老梁'
}
}
})
// 非响应式
// vm.formData.name = '邻村寡妇'
</script>
// 响应式1
// vm.formData = Object.assign({}, vm.formData, {
// name: '邻村寡妇'
// })
// console.log(vm.formData)
// 响应式2
// Vue.set(vm.formData, 'name', '邻村寡妇')
// console.log(vm.formData)
响应式:初始化时定义熟悉
xxxxxxxxxx
<div id="app">
{{formData.username}} {{formData.name}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
formData: {
username: '隔壁老梁',
name: '邻村寡妇'
}
}
})
</script>
响应式:Object.assign()方法
- 创建一个新的对象然后覆盖原有对象
xxxxxxxxxx
<div id="app">
{{formData.username}} {{formData.name}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
formData: {
username: '隔壁老梁',
name: '邻村寡妇'
}
}
})
// 响应式1
vm.formData = Object.assign({}, vm.formData, {
name: '邻村寡妇'
})
console.log(vm.formData)
</script>
响应式:Vue.set()
- 将属性设置为响应式
- 组件内部也可以使用
this.$set
来调用这个方法。
xxxxxxxxxx
<div id="app">
{{formData.username}} {{formData.name}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
formData: {
username: '隔壁老梁',
name: '邻村寡妇'
}
}
})
// 响应式
Vue.set(vm.formData, 'name', '邻村寡妇')
console.log(vm.formData)
</script>
设置数组的元素
- 不能直接使用索引来设置数据的元素
xxxxxxxxxx
<div id="app">
{{dogs[2]}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
dogs: ['小明', '小红', '小刚']
}
})
vm.dogs[2] = '小强'
</script>
设置数组的元素:使用.splice()方法
xxxxxxxxxx
<div id="app">
{{dogs[2]}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
dogs: ['小明', '小红', '小刚']
}
})
vm.dogs.splice(2,1,'小强')
</script>
设置数组的元素:使用Vue.set()方法
xxxxxxxxxx
<div id="app">
{{dogs[2]}}
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
dogs: ['小明', '小红', '小刚']
}
})
Vue.set(vm.dogs,2,'小强')
</script>
设置数组的长度
Vue
不能自动让空元素填充数组至该长度或者截掉数组的尾部,Vue
不能检测到该操作对数组的任何更改。- 这一方法只能用于缩短数组,并不能扩展它的长度。
xxxxxxxxxx
<script>
const vm = new Vue({
data: {
dogs: ['小明', '小红', '小刚']
}
})
vm.dogs.splice(2)
console.log(vm.dogs);
</script>
双向数据绑定
- 在
inputText
值变化时才更新输入框的值,反过来则不行。
xxxxxxxxxx
<div id="app">
<input type="text" :value="inputText" >
<p>inputText:{{inputText}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
inputText: '隔壁老梁'
}
})
</script>
- 使用
v-model
指令实现双向绑定
xxxxxxxxxx
<div id="app">
<input type="text" v-model="inputText" >
<p>inputText:{{inputText}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data: {
inputText: '隔壁老梁'
}
})
</script>
使用
v-model
会忽略value
、checked
和selected
属性。
- 单选框存储在
data
中的值等于当前选中的单选输入框的value
属性的值
xxxxxxxxxx
<div id="app">
<label><input type="radio" v-model="value" value="一" />一</label>
<label><input type="radio" v-model="value" value="二" />二</label>
<label><input type="radio" v-model="value" value="三" />三</label>
<p>选中的value值为{{value}}</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
value: '一'
}
})
</script>
当第一个选择框选中时,value的值是一;当第二个选择框选中时,value的值是二,以此类推。
动态设置HTML
- 渲染HTML到页面上用
v-html
指令
xxxxxxxxxx
<div v-html="myHtml"></div>
慎用这此功能,从某个变量中取出
HTML
并输出到页面上,你可能将自己暴露在XSS
风险中。只用v-html
处理你信任的数据。
方法
- 在Vue的模板里,函数被定义为方法来使用。
xxxxxxxxxx
<div id="app">
<input type="text" v-model="status">
<p>当前状态:{{statusFromId(status)}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
status:2
},
methods: {
statusFromId(id){
const status = ({
0: '睡觉',
1: '吃饭',
2: '学习Vue'
})[id];
return status || '未知状态:' + id;
}
},
})
</script>
- 任何可以使用JavaScript表达式的地方都可以使用方法。
xxxxxxxxxx
<div id="app">
<ul>
<li v-for="number in filterPositive(numbers)">{{number}}</li>
</ul>
</div>
<script>
new Vue({
el: '#app',
data: {
numbers: [-5, 0, 2, -1, 1, 0.5]
},
methods: {
filterPositive (numbers) {
return numbers.filter(number => number >= 0)
}
}
})
</script>
上面这个例子中的方法接收一个数组,然后返回一个过滤掉所有负数的新数组,因此页面上会输出一个正数列表。
this
- 在方法中,
this
指向该方法所属的组件。可以使用this
访问data
对象的属性和其他方法。
xxxxxxxxxx
<div id="app">
<p>所有正数的总和是{{getPositiveNumbersSum()}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
numbers: [-5, 0, 2, -1, 1, 0.5]
},
methods: {
getPositiveNumbers () {
// 使用的是this.numbers,它直接指向data对象的numbers数组
return this.numbers.filter(number => number >= 0)
},
getPositiveNumbersSum () {
// 直接使用getPositiveNumbers方法,用reduce进行累加处理
return this.getPositiveNumbers().reduce((sum, val) => sum + val)
}
}
})
</script>
在这个例子中,
getPositiveNumbers
方法中的this.numbers
指向data
对象中的numbers
数组,在前面的例子中我们以参数的方式传递这个数组;而this.getPositiveNumbers()
则指向methods
对象中被命名为该名称的方法。
计算属性
- 计算属性,可以像访问data对象的属性那样访问它,但需要以函数的方式定义它。
xxxxxxxxxx
<div id="app">
<p>数字的总和是:{{numberTotal}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
numbers: [5, 8, 3]
},
computed: {
numberTotal () {
return this.numbers.reduce((sum, val) => sum + val)
}
}
})
</script>
将计算数字总和的语句,单独定义在别处明显更加方便和可读。
computed和methods有什么区别?
- 计算属性会被缓存:计算属性被多次调用,其中的代码只会执行一次,之后的每次调用都会使用被缓存的值。
- 只有当计算属性的依赖发生变化时,代码才会被再次执行。
- 可以设置计算属性的值,并且在设置过程中做一些操作。
- 用console.log()语句来观察计算属性缓存特性。
xxxxxxxxxx
<div id="app">
<input type="text" v-model="value">
<p>{{doubleValue}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
value:10
},
computed: {
doubleValue () {
console.log('我被执行了!');
return this.value * 2
}
}
})
</script>
只有当应用初始化和每次value发生变化时,字符串才会被输出到控制台。
- 置计算属性的值,并且在设置过程中做一些操作。实现这一点需要将计算属性由函数改为带有
get
和set
属性的对象。(不清楚get
和set
属性的可以先了解一下)
xxxxxxxxxx
<div id="app">
<p>数字的总和是:{{numberTotal}}</p>
<p>数字的总和是:{{num}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
numbers: [5, 8, 3,15]
},
computed: {
numberTotal: {
get () {
return this.numbers.reduce((sum, val) => sum + val)
},
set (newValue) {
const oldValue = this.numberTotal
const difference = newValue - oldValue
this.numbers.push(difference)
}
},
num(){
// return this.numberTotal+5
return this.numberTotal+=5
},
}
})
</script>
使用data对象、方法还是计算属性?
data
对象,使用它可以存储字符串、数组和对象等数据;方法(
methods
),使用它可以存储函数并在模板中调用;计算属性,使用它可以将函数存储下来,然后像访问
data
对象中的属性一样调用。使用场景
- 如果需要接收一个参数,那么肯定要用方法,而不是
data
对象或者计算属性:这两者都不能接收参数。 - data对象最适合纯粹的数据:如果想将数据放在某处,然后在模板、方法或者计算属性中使用,那么可以把它放在data对象中。后面也许还会更新它。
- 当你希望为模板添加函数功能时,最好使用方法:给方法传递数据,然后它们会对数据进行处理,最终可能返回不同的数据结果。
- 计算属性适用于执行更加复杂的表达式,这些表达式往往太长或者需要频繁地重复使用,所以不想在模板中直接使用。计算属性往往和其他计算属性或者data对象一起使用,基本上就像是data对象的一个扩展和增强版本。
- 如果需要接收一个参数,那么肯定要用方法,而不是
侦听器
- 侦听器可以监听data对象属性或者计算属性的变化。
xxxxxxxxxx
<div id="app">
<input type="text" v-model="count">
<p>{{count}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
count:0
},
watch:{
count(){
alert('我变了');
}
}
})
</script>
侦听器很适合用于处理异步操作。
- 让用户输入的输入框,但是想将5秒前的输入内容显示到页面上。
xxxxxxxxxx
<div id="app">
<input type="text" v-model="inputValue">
<p>5秒之后,显示输入的值为:{{oldInputValue}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
inputValue:'',
oldInputValue:''
},
watch:{
inputValue(){
const newValue = this.inputValue;
setTimeout(()=>{
this.oldInputValue = newValue
},5000)
}
}
})
</script>
监听data对象中某个对象的属性
xxxxxxxxxx
<div id="app">
<input type="text" v-model="formData.username">
<p>输入的值为:{{formData.username}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
formData:{
username:''
}
},
watch:{
'formData.username'(){
alert('我变了');
}
}
})
</script>
获取旧值
当监听的属性发生变化时,侦听器会被传入两个参数:所监听属性的当前值和原来的旧值。
- 这一特性可以用来了解到底发生了什么变化:
xxxxxxxxxx
<div id="app">
<input type="text" v-model="formData.username">
<p>输入的值为:{{formData.username}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
formData:{
username:0
}
},
watch:{
'formData.username'(val,oldVal){
console.log('新值为:',val,'旧值为:',oldVal);
}
}
})
</script>
深度监听
监听整个对象的变化
- 如果你正在监听
formData
对象并且修改了formData.username
,对应的侦听器并不会触发,它只在formData
对象被整个替换时触发。 - 监听整个对象被称作深度监听,通过将deep选项设置为true来开启这一特性:
xxxxxxxxxx
<div id="app">
<input type="text" v-model="formData.username" />
<p>输入的值为:{{formData.username}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
formData: {
username: 0
}
},
watch: {
formData: {
handler (val, oldVal) {
console.log('新值为:', val, '旧值为:', oldVal)
},
deep: true
}
},
mounted () {
this.formData = {
username: '隔壁老梁'
}
}
})
</script>
- 如果你正在监听
过滤器
- 过滤器是一种在模板中处理数据的便捷方式
将价格单位从分转换为元、格式化为两位小数,同时添加美元符号。
xxxxxxxxxx
<div id="app">
<p>商品1花费了{{productOneCost | formatCost}}</p>
<p>商品2花费了{{productTwoCost | formatCost}}</p>
<p>商品3花费了{{productThreeCost | formatCost}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
productOneCost: 1000,
productTwoCost: 2000,
productThreeCost: 3000
},
filters:{
FormatCost(value){
// toFixed() 方法可把 Number 四舍五入为指定小数位数的数字。
return '$' + (value / 100).toFixed(2)
}
}
})
</script>
- 增加货币换算功能
xxxxxxxxxx
<div id="app">
<p>商品1花费了{{productOneCost | formatCost('$')}}</p>
</div>
<script>
new Vue({
el: '#app',
data: {
productOneCost: 1000
},
filters:{
FormatCost(value,symbol){
return symbol + (value / 100).toFixed(2)
}
}
})
</script>
- 在v-bind中使用全局过滤器
xxxxxxxxxx
<div id="app">
<input type="text" :value="productCost | formatCost('$')" />
</div>
<script>
Vue.filter('formatCost', function (value, symbol) {
return symbol + (value / 100).toFixed(2)
})
new Vue({
el: '#app',
data: {
productCost: 1000
}
})
</script>
注意事项
- 过滤器是组件中唯一不能使用this来访问数据或者方法的地方。因为过滤器应该是纯函数,也就是说对于同样的输入每次都返回同样的输出,而不涉及任何外部数据。如果想在过滤器中访问其他数据,可以将它作为参数传入。
- 只可以在插值和
v-bind
指令中使用过滤器。
使用ref直接访问元素
- 使用
ref
访问一个元素,只需要将这个元素的ref属性设置为字符串。
xxxxxxxxxx
<div id="app">
<div ref="myDiv">我是ref</div>
<button @click="myDivClick">获取ref</button>
</div>
<script>
new Vue({
el: '#app',
data: {},
methods: {
myDivClick () {
console.log(this.$refs.myDiv)
}
}
})
</script>
这个元素会被存储到
this.$refs
这个对象中,对应的键名就是为元素的ref
属性设置的值。
this.$refs
只包含当前组件内部元素的引用。
输入和事件
- 使用
v-on
指令将事件侦听器绑定到元素上。
xxxxxxxxxx
<div id="app">
<button @click="counter++">点赞</button>
<p>点了{{counter}}次</p>
</div>
<script>
new Vue({
el: '#app',
data: {
counter: 0
}
})
</script>
- 也可以提供一个方法名,当按钮被单击时会调用该方法名对应的方法。
xxxxxxxxxx
<div id="app">
<button @click="increase">点赞</button>
<p>点了{{counter}}次</p>
</div>
<script>
new Vue({
el: '#app',
data: {
counter: 0
},
methods: {
increase(e){
this.counter++
}
},
})
</script>
使用方法和内联代码的一个明显区别
- 使用方法:事件对象会作为第一个参数传入。这个事件对象是原生的
DOM
事件对象,如果你使用JavaScript
内建的.addEventListener()
方法添加事件监听器,会得到相同的事件对象,而且它非常有用,例如可以获取键盘事件的keyCode
值。 - 使用内联代码:也可以通过
$event
变量访问事件对象。当你将同一事件侦听器添加到多个元素,并希望了解是哪个元素触发的事件时,这一功能会很有用。
- 使用方法:事件对象会作为第一个参数传入。这个事件对象是原生的
v-on简写
v-on:click
简写为@click
。
事件修饰符
使用修饰符来修改事件侦听器或者事件本身。
当链接被单击时阻止页面的跳转(阻止执行事件默认行为)
.prevent
修饰符
xxxxxxxxxx
<a @click.prevent="handleClick">...</a>
阻止事件继续传播,以避免在父级元素上触发事件
.stop
修饰符
xxxxxxxxxx
<a @click.stop="handleClick">...</a>
只在第一次触发事件的时候触发事件侦听器
.once
修饰符
使用捕获模式
.capture
修饰符
xxxxxxxxxx
<a @click.capture="handleClick">...</a>
监听元素自身而不是它的子元素上触发的事件
.self
修饰符
具体修饰符可以看官方文档
生命周期钩子
Vue
实例的created
属性,它会在组件创建完成时被调用。生命周期钩子:
- 从组件被创建并添加到
DOM
,到组件被销毁的整个过程——的各个阶段被调用的函数。
- 从组件被创建并添加到
8个生命周期钩子
生命周期钩子 | 说明 |
---|---|
beforeCreate | 执行new Vue() 时初始化。 |
created | 响应式功能被初始化 |
beforeMount | 解析模板,开始创建DOM 元素 |
mounted | 创建DOM 节点 |
beforeUpdate | 在处理更新前 |
updated | 在应用更新之后 |
beforeDestroy | 在组件从DOM 上被移除前 |
destroyed | 在组件从DOM 上被移除后 |
mounted
钩子触发时并不保证元素已经被添加到DOM
上。想保证元素已经被添加,调用Vue.nextTick()
方法,并传入一个回调函数,在回调函数中添加需要在元素被添加到DOM
之后运行的代码。
- 调用
Vue.nextTick()
方法
xxxxxxxxxx
<div id="app">
<p>{{message}}</p>
</div>
<script>
const vm = new Vue({
el: '#app',
data () {
return {
message: '雷猴,世界。'
}
}
})
vm.message = '吔屎啦你'
console.log(vm.$el.textContent === '吔屎啦你') // false
Vue.nextTick(function () {
console.log(vm.$el.textContent === '吔屎啦你') // true
})
</script>
梳理
生命周期钩子 | 说明 |
---|---|
beforeCreate | 实例初始化前被触发。 |
created | 实例初始化之后、被添加到DOM 之前触发。 |
beforeMount | 元素已经准备好被添加到DOM ,但还没有添加的时候触发。 |
mounted | 元素创建后触发(但并不一定已经添加到了DOM ,可以用nextTick 来保证这一点)。 |
beforeUpdate | 由于数据更新将要对DOM 做一些更改时触发。 |
updated | DOM 的更改已经完成后触发。 |
beforeDestroy | 组件即将被销毁并且从DOM 上移除时触发。 |
destroyed | 在组件被销毁后触发。 |
只需要记住4个(
created
、mounted
、updated
和destroyed
),然后可以推导出其他4个。
自定义指令
自定义指令方式:
- 组件的
directives
属性 Vue.directive()
注册一个全局指令
- 组件的
xxxxxxxxxx
<div id="app">
<p v-blink>我闪了~~</p>
</div>
<script>
Vue.directive('blink',{
bind(el) {
let isVisible = true;
setInterval(()=>{
isVisible =! isVisible;
el.style.visibility = isVisible ? 'visible':'hidden';
},1000);
}
})
new Vue({
el: '#app'
})
</script>
指令的钩子函数
指令的钩子函数 | 说明 |
---|---|
bind | 在指令绑定到元素时被调用 |
inserted | 在绑定的元素被添加到父节点时被调用 |
update | 在绑定该指令的组件节点被更新时调用,但是该组件的子组件可能此时还未更新。 |
componentUpdated | 在组件的子组件都更新完成后调用。 |
unbind | 用于指令的拆除,当指令从元素上解绑时会被调用。 |
钩子函数参数
- 略
过渡动画
- 在切换显示状态时让div元素渐隐或渐现。
xxxxxxxxxx
<style>
.fade-enter-active,
.fade-leave-active {
transition: opacity 0.5s;
}
.fade-enter,
.fade-leave-to {
opacity: 0;
}
</style>
</head>
<body>
<div id="app">
<button @click="divVisible = !divVisible">切换可见性</button>
<transition name="fade">
<div v-if="divVisible">时而想开,时而自闭</div>
</transition>
</div>
<script>
new Vue({
el: '#app',
data () {
return {
divVisible: true
}
}
})
</script>
</body>
工作原理:,
Vue
获取tansition
组件的name
属性值,然后使用它在过渡的各个节点为包含的元素添加类名。当元素被添加到文档或者从文档中移除时,会分别应用enter
和leave
两类过渡。
{name}-enter
- 这个类名会在元素被插入
DOM
时加入,然后在下一帧立刻移除。 - 使用它来设置那些需要在元素开始进入过渡时移除的
CSS
属性。
- 这个类名会在元素被插入
{name}-enter-active
- 这个类名会在元素整个动画阶段应用。它和
-enter
类名同时被添加,然后在动画完成时被移除。 - 这个类适用于设置
transition
这个CSS
属性,以设置过渡的时间长度、过渡的属性和使用的曲线函数。
- 这个类名会在元素整个动画阶段应用。它和
{name}-enter-to
- 这个类名会在
-enter
类名从元素上移除的同时添加到元素上。 - 它适合用来设置那些在元素开始进入过渡时添加的
CSS
属性,但我通常发现,在-enter
类上设置与之相反的过渡属性会更好用一些。
- 这个类名会在
- .略.......................(动画类名比较多,可以查看官方文档结合CSS去实践。)。
总结
在这一章中,我们着眼于Vue的一些基础用法:
· 了解了一些使用Vue的原因。
· 了解了如何使用CDN或者webpack安装和配置Vue。
· 了解了Vue的语法:如何使用模板、data对象和指令将数据显示到页面上。
· 了解了v-if指令和v-show指令的区别。
· 了解了如何使用v-for在模板中进行循环。
· 了解了如何使用v-bind指令将data对象的属性绑定到HTML元素的属性上。
· 了解了Vue如何在数据更新时自动地更新页面上显示的内容:这一特性被称作响应式。
· 了解了双向数据绑定:使用v-model将数据显示在输入框中,以及当输入框的输入值被改变时更新data对象。
· 了解了如何使用v-html指令将data对象中的数据直接设置为一个元素内部的HTML内容。
· 了解了如何使用方法,从而可以在模板中和整个Vue实例中访问函数。同时我们还了解了方法中this的指向。
· 了解了如何使用计算属性来创建可访问的值,就像访问data对象的属性一样,但是它们是在运行时计算得到的,并且是以函数的形式被定义的。
· 了解了如何使用侦听器来监听data对象的属性或计算属性的变化,并且在变化发生时进行一些处理——但是通常情况下应该避免使用侦听器,计算属性往往是不错的选择。
· 了解了过滤器,一种在模板中处理数据的便捷方法——例如,格式化数据。
· 了解了如何使用ref直接访问元素,在使用Vue不支持的第三方库或者是做一些Vue自身不支持的操作时,可以使用它。
· 了解了使用v-on实现事件绑定,以及它的简写语法:在事件名称前添加@前缀。
· 了解了Vue实例的生命周期,以及如何在钩子函数中运行代码。
· 了解了如何创建自定义指令。
· 了解了如何使用Vue提供的CSS过渡和JavaScript动画功能。
Comments | NOTHING