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指向的是同一个地址空间,值是修改之后的值,所以是一样的。