Vue的生命周期
vue的生命周期图示

生命周期示例day02/03.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue生命周期</title>
<script src="js/vue.js"></script>
<script>
window.onload=function(){
let vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany'
},
methods:{
update(){
this.msg='欢迎来到南京网博!';
},
destroy(){
// this.$destroy();
vm.$destroy();
}
},
beforeCreate(){
alert('组件实例刚刚创建,还未进行数据观测和事件配置');
},
created(){ //常用!!!
alert('实例已经创建完成,并且已经进行数据观测和事件配置');
},
beforeMount(){
alert('模板编译之前,还没挂载');
},
mounted(){ //常用!!!
alert('模板编译之后,已经挂载,此时才会渲染页面,才能看到页面上数据的展示');
},
beforeUpdate(){
alert('组件更新之前');
},
updated(){
alert('组件更新之后');
},
beforeDestroy(){
alert('组件销毁之前');
},
destroyed(){
alert('组件销毁之后');
}
});
}
</script>
</head>
<body>
<div id="itany">
{{msg}}
<br>
<button @click="update">更新数据</button>
<button @click="destroy">销毁组件</button>
</div>
</body>
</html>
计算属性
1.基本用法
计算属性也是用来存储数据的,但具有以下几个特点
a.数据可以进行逻辑处理操作
b.对计算属性中的数据进行监视
计算属性取值不能向定义普通属性那样定义,需要定义函数,函数必须有返回值称为get值,调用的时候和普通属性是一样的{{}}
示例day02/04.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
<script src="js/vue.js"></script>
<script>
window.onload=function(){
let vm=new Vue({
el:'#itany',
data:{ // 普通属性
msg:'welcome to itany'
},
computed:{ // 计算属性
msg2:function(){
return '欢迎来到南京网博';
}
}
});
}
</script>
</head>
<body>
<div id="itany">
<!-- 1,基本用法 -->
<h2>{{msg}}</h2>
<h2>{{msg2}}</h2>
</div>
</body>
</html>
假如想要把msg以空格为分隔符然后反向输出,下面有两种方法
1,在数据展示时进行逻辑处理
2,使用计算属性定义函数在函数内处理
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
<script src="js/vue.js"></script>
<script>
window.onload=function(){
let vm=new Vue({
el:'#itany',
data:{ // 普通属性
msg:'welcome to itany'
},
computed:{ // 计算属性
msg2:function(){
return '欢迎来到南京网博';
},
reverseMsg:function(){
return this.msg.split(' ').reverse().join(' ');
}
}
});
}
</script>
</head>
<body>
<div id="itany">
<!-- 1,基本用法 -->
<h2>{{msg}}</h2>
<h2>{{msg2}}</h2>
<!-- 对数据进行处理 -->
<!-- 缺点:在模板中放入了太多逻辑处理代码 -->
<h2>{{msg.split(' ').reverse().join(' ')}}</h2>
<!-- 在计算属性内定义函数处理 -->
<h2>{{reverseMsg}}</h2>
</body>
</html>
页面显示,两种处理方法效果是一样的

2.计算属性 vs 方法
将计算属性的get函数定义为一个方法也可以实现类似的功能
区别:
a.计算属性是基于它的依赖进行更新的,只有在相关依赖发送改变时才能更新变化
b.计算属性是缓存的,只要相关依赖没有改变,多次访问计算属性得到的值是之前缓存的计算结果,不会多次执行
示例day02/04html 计算属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<!-- 1,基本用法 -->
<h2>{{msg}}</h2>
<h2>{{msg2}}</h2>
<!-- 对数据进行处理 -->
<!-- 缺点:在模板中放入了太多逻辑处理代码 -->
<h2>{{msg.split(' ').reverse().join(' ')}}</h2>
<!-- 在计算属性内定义函数处理 -->
<h2>{{reverseMsg}}</h2>
<button @click="change">修改值</button>
<!--
2.计算属性 vs 方法
-->
<!-- <h2>{{num1}}</h2>
<h2>{{num2}}</h2>
<h2>{{getNum2()}}</h2> -->
<button onclick="fn()">测试</button>
</div>
<script>
let vm=new Vue({
el:'#itany',
data:{ // 普通属性
msg:'welcome to itany',
num1:7
},
computed:{ // 计算属性
msg2:function(){
return '欢迎来到南京网博';
},
reverseMsg:function(){
// 可以包含逻辑处理操作,同时reverseMsg依赖于msg
return this.msg.split(' ').reverse().join(' ');
},
num2:function(){
console.log(new Date())
return this.num1-1
}
},
methods:{
change(){
// this.msg='i love you'
this.num1=666;
},
getNum2(){
console.log('num2'+new Date())
return this.num1-1;
}
}
});
function fn(){
setInterval(function(){
// console.log(vm.getNum2());
console.log(vm.num2);
},1000);
}
</script>
</body>
</html>
解析:函数fn是单独定义的不属于vue实例,点击测试时候调用,间隔1秒执行打印 vm.num2是打印计算属性
页面输出

修改代码
调用方法输出而不是计算属性
console.log(vm.getNum2()); // console.log(vm.num2);
页面输出

3,.get和set
计算属性由两部分组成:get和set,分别用来获取计算属性和设置计算属性
默认只有get,如果需要set,要自己添加
计算属性赋值不能给自己赋值而需要给该计算属性依赖的值赋值,示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>计算属性</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<!-- 1,基本用法 -->
<h2>{{msg}}</h2>
<h2>{{msg2}}</h2>
<!-- 对数据进行处理 -->
<!-- 缺点:在模板中放入了太多逻辑处理代码 -->
<h2>{{msg.split(' ').reverse().join(' ')}}</h2>
<!-- 在计算属性内定义函数处理 -->
<h2>{{reverseMsg}}</h2>
<button @click="change">修改值</button>
<!--
2.计算属性 vs 方法
-->
<!-- <h2>{{num1}}</h2>
<h2>{{num2}}</h2>
<h2>{{getNum2()}}</h2> -->
<button onclick="fn()">测试</button>
<!--
3,get和set
-->
<h2>{{num2}}</h2>
<button @click="change2">修改计算属性</button>
</div>
<script>
let vm=new Vue({
el:'#itany',
data:{ // 普通属性
msg:'welcome to itany',
num1:7
},
computed:{ // 计算属性
msg2:function(){
return '欢迎来到南京网博';
},
reverseMsg:function(){
// 可以包含逻辑处理操作,同时reverseMsg依赖于msg
return this.msg.split(' ').reverse().join(' ');
},
num2:{
get:function(){
console.log(new Date())
return this.num1-1
},
set:function(val){
// console.log('修改num2的值')
// this.num2=val;
this.num1=val;
}
}
},
methods:{
change(){
// this.msg='i love you'
this.num1=666;
},
getNum2(){
console.log('num2'+new Date())
return this.num1-1;
},
change2(){
this.num2=111;
},
}
});
function fn(){
setInterval(function(){
console.log(vm.getNum2());
// console.log(vm.num2);
},1000);
}
</script>
</body>
</html>
解析:点击修改计算属性调用change2方法,在这个方法内给num2赋值给111,当出现赋值操作则调用该计算属性的set方法,传递的参数val就是change2中设置的的值111,但是不能在set方法内直接修改num2 的值,如果直接修改会因为重复调用溢出栈报错,需要修改的是是num1的值,因为num2依赖num1所以num2的值也修改了
页面显示


四,vue实例的属性和方法
1.属性
vm.$el vm.$data vm.$options vm.$refs
示例05.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue实例的属性和方法</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
{{msg}}
<h2 ref="hello">你好</h2>
<p ref='world'>世界</p>
<hr>
<!-- <p ref='title'>标题:{{name}}</p> -->
</div>
<script>
vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany',
},
name:'liuym',
age:24,
show:function(){
console.log('show')
},
});
// 属性
// vm.属性名,获取data中的属性
console.log(vm.msg);
// vm.$el 获取vue实例关联的元素
console.log(vm.$el)
vm.$el.style.color='red'
// vm.$data 获取数据对象
console.log(vm.$data)
// vm.$options 用来获取自定义属性
console.log(vm.$options.name)
vm.$options.show();
// vm.$refs 获取所有添加ref属性的元素
console.log(vm.$refs.hello); // DOM对象
vm.$refs.hello.style.color='red';
// 方法
// 手动挂载vue实例
// vm.$mount('#itany')
// var vm=new Vue({
// data:{
// msg:'欢迎来到南京网博',
// name:'tom'
// }
// }).$mount('#itany');
// vm.$destory() 销毁实例 一般不手动调用
// vm.$destory();
// vm.$nextTick(callback)在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便能获取更新后的DOM
// 修改数据
// vm.name='汤姆';
// DOM还没有更新完 Vue实现响应式并不是数据发生改变之后DOM立即变化,需要按一定的策略进行DOM更新,需要时间
// console.log(vm.$refs.title.textContent);
// vm.$nextTick(function(){
// // DOM更新完成再执行此代码
// console.log(vm.$refs.title.textContent);
// });
</script>
</body>
</html>
页面显示

2.方法
vm.$mount() vm.$destroy() vm.$nextTick() vm.$set() vm.$delete() vm.$watch()
mount手动挂载实例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue实例的属性和方法</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
{{msg}}
<h2 ref="hello">你好</h2>
<p ref='world'>世界</p>
<hr>
<!-- <p ref='title'>标题:{{name}}</p> -->
</div>
<script>
// vm=new Vue({
// el:'#itany',
// data:{
// msg:'welcome to itany',
// },
// name:'liuym',
// age:24,
// show:function(){
// console.log('show')
// },
// });
// 属性
// vm.属性名,获取data中的属性
// console.log(vm.msg);
// vm.$el 获取vue实例关联的元素
// console.log(vm.$el)
// vm.$el.style.color='red'
// vm.$data 获取数据对象
// console.log(vm.$data)
// vm.$options 用来获取自定义属性
// console.log(vm.$options.name)
// vm.$options.show();
// vm.$refs 获取所有添加ref属性的元素
// console.log(vm.$refs.hello); // DOM对象
// vm.$refs.hello.style.color='red';
// 方法
// 手动挂载vue实例
// vm.$mount('#itany')
var vm=new Vue({
data:{
msg:'欢迎来到南京网博',
name:'tom'
}
}).$mount('#itany');
// vm.$destory() 销毁实例 一般不手动调用
// vm.$destory();
// vm.$nextTick(callback)在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便能获取更新后的DOM
// 修改数据
// vm.name='汤姆';
// DOM还没有更新完 Vue实现响应式并不是数据发生改变之后DOM立即变化,需要按一定的策略进行DOM更新,需要时间
// console.log(vm.$refs.title.textContent);
// vm.$nextTick(function(){
// // DOM更新完成再执行此代码
// console.log(vm.$refs.title.textContent);
// });
</script>
</body>
</html>
手动挂载的效果和以下代码效果是一样的
vm=new Vue({
el:'#itany',
data:{
msg:'welcome to itany',
},
name:'liuym',
age:24,
show:function(){
console.log('show')
},
});
vm.$nextTick(callback)示例
vm.$nextTick(callback)在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便能获取更新后的DOM
不使用nextTick在修改以后
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vue实例的属性和方法</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
{{msg}}
<h2 ref="hello">你好</h2>
<p ref='world'>世界</p>
<hr>
<p ref='title'>标题:{{name}}</p>
</div>
<script>
// vm=new Vue({
// el:'#itany',
// data:{
// msg:'welcome to itany',
// },
// name:'liuym',
// age:24,
// show:function(){
// console.log('show')
// },
// });
// 属性
// vm.属性名,获取data中的属性
// console.log(vm.msg);
// vm.$el 获取vue实例关联的元素
// console.log(vm.$el)
// vm.$el.style.color='red'
// vm.$data 获取数据对象
// console.log(vm.$data)
// vm.$options 用来获取自定义属性
// console.log(vm.$options.name)
// vm.$options.show();
// vm.$refs 获取所有添加ref属性的元素
// console.log(vm.$refs.hello); // DOM对象
// vm.$refs.hello.style.color='red';
// 方法
// 手动挂载vue实例
// vm.$mount('#itany')
var vm=new Vue({
data:{
msg:'欢迎来到南京网博',
name:'tom'
}
}).$mount('#itany');
// vm.$destory() 销毁实例 一般不手动调用
// vm.$destory();
// vm.$nextTick(callback)在DOM更新完成后再执行回调函数,一般在修改数据之后使用该方法,以便能获取更新后的DOM
// 修改数据
vm.name='汤姆';
// DOM还没有更新完 Vue实现响应式并不是数据发生改变之后DOM立即变化,需要按一定的策略进行DOM更新,需要时间
console.log(vm.$refs.title.textContent);
// vm.$nextTick(function(){
// // DOM更新完成再执行此代码
// console.log(vm.$refs.title.textContent);
// });
</script>
</body>
</html>
页面显示

修改代码使用nextTick绑定在函数内执行
// console.log(vm.$refs.title.textContent);
vm.$nextTick(function(){
// DOM更新完成再执行此代码
console.log(vm.$refs.title.textContent);
});
页面显示

方法
vm.$set(object,key,value) vm.$delete(object,key) vm.$watch(data,callback[,options])
set方法示例 day02/06.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加和删除属性</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<button @click="doUpdate">修改属性</button>
<button @click="doAdd">添加属性</button>
<hr>
<h2>{{user.name}}</h2>
<h2>{{user.age}}</h2>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
user:{
id:1001,
name:'tom'
}
},
methods:{
doUpdate(){
this.user.name='汤姆';
},
doAdd(){
this.user.age=25; // 通过普通方式为对象添加属性时vue无法实时监控到
// this.$set(this.user,'age',18); // 通过vue实例的$set方法可以实时监视
// Vue.set(this.user,'age',19)
// if(this.user.age){
// this.user.age++;
// }else{
// Vue.set(this.user,'age',1);
// }
},
}
});
</script>
</body>
</html>
user本身没有age属性,使用doAdd方法添加这个属性,页面显示


如果需要监控实时显示,修改代码使用set方法,修改方法doAdd()代码
this.$set(this.user,'age',18);
页面显示

以下代码是添加属性的全局方式,和上面代码实现的效果是一样的
Vue.set(this.user,'age',19)
一般情况下set方法不直接使用而是做一个判断再使用,例如需要从user中获取这个属性,如果有这个属性则给这个属性值+1,赋值设置这个属性值为1
if(this.user.age){
this.user.age++;
}else{
Vue.set(this.user,'age',1);
}
delete方法演示
06.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>添加和删除属性</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<button @click="doUpdate">修改属性</button>
<button @click="doAdd">添加属性</button>
<button @click="doDelete">删除属性</button>
<hr>
<h2>{{user.name}}</h2>
<h2>{{user.age}}</h2>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
user:{
id:1001,
name:'tom'
}
},
methods:{
doUpdate(){
this.user.name='汤姆';
},
doAdd(){
// this.user.age=25; // 通过普通方式为对象添加属性时vue无法实时监控到
this.$set(this.user,'age',18); // 通过vue实例的$set方法可以实时监视
// Vue.set(this.user,'age',19)
// if(this.user.age){
// this.user.age++;
// }else{
// Vue.set(this.user,'age',1);
// }
},
doDelete(){
if(this.user.age){
// delete this.user.age; // 无效
Vue.delete(this.user,'age');
}
},
}
});
</script>
</body>
</html>
页面显示

watch方法示例
有两种方法监视数据day02/07.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监视数据的变化</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<input type='text' v-model="name">
<h3> {{name}}</h3>
<hr>
<input type='text' v-model="age">
<h3> {{age}}</h3>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
name:'tom',
age:23
},
watch:{ // 方式2,使用vue实例提供的watch选项
age:(newValue,oldValue)=>{
console.log('age被修改了,原值'+oldValue+',新值'+newValue);
}
}
});
// 监视数据变化,没有全局方法
// 方式1:使用vue实例提供的$watch()方法
vm.$watch('name',function(newValue,oldValue){
console.log('name被修改了,原值'+oldValue+',新值'+newValue);
});
</script>
</body>
</html>
监视数据传递两个参数一个是修改后的新值一个是旧值
页面显示

选项:deep 深度监视
为了发现对象内部值的变化,可以在选项参数中指定 deep: true。注意监听数组的变更不需要这么做。
示例,监听一个数组的变更
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>监视数据的变化</title>
<script src="js/vue.js"></script>
</head>
<body>
<div id="itany">
<input type='text' v-model="name">
<h3> {{name}}</h3>
<hr>
<input type='text' v-model="age">
<h3> {{age}}</h3>
<hr>
<input type='text' v-model="user.name">
<h3> {{user.name}}</h3>
</div>
<script>
var vm=new Vue({
el:'#itany',
data:{
name:'tom',
age:23,
user:{
name:'汤姆'
}
},
watch:{ // 方式2,使用vue实例提供的watch选项
age:(newValue,oldValue)=>{
console.log('age被修改了,原值'+oldValue+',新值'+newValue);
},
user:(newValue,oldValue)=>{
console.log('user被修改了,原值'+oldValue+',新值'+newValue);
},
}
});
// 监视数据变化,没有全局方法
// 方式1:使用vue实例提供的$watch()方法
vm.$watch('name',function(newValue,oldValue){
console.log('name被修改了,原值'+oldValue+',新值'+newValue);
});
</script>
</body>
</html>
解析:想要监控数组user的变更,但是页面显示,因为只是修改了数组user下面属性name的值,但是数组user对name属性的指向并没有变化,需要深度监视需要加deep选项

修改代码如下
// 深度监视
user:{
handler:(newValue,oldValue) => {
console.log('user被修改啦,原值:'+oldValue.name+',新值:'+newValue.name);
},
deep:true //深度监视,当对象中的属性发生变化时也会监视
}
页面显示

newValue和oldValue指向的是同一个地址空间,值是修改之后的值,所以是一样的。