本次Vue学习基于尚硅谷天禹老师的视频课程。
官方文档:https://cn.vuejs.org/v2/guide/
1、初识Vue
Vue是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
Vue的特点:
1、采用组件化模式,提高代码的复用率,让代码更好维护;
2、声明式编码,让编码人员无需直接操作DOM,提高开发效率;
3、使用虚拟DOM和优秀的Diff算法,尽量复用DOM节点;
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>初识Vue</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 <link rel="shortcut icon" type="image/x-icon" href="favicon.ico"/> 9 </head> 10 <body> 11 <!-- 12 前置: 13 1、强制刷新shift+F5 14 2、解决网页标签favicon.ico缺失的问题,内部服务器 15 3、new Vue({这里是配置对象,要用专有名词,如el,methods}) 16 初识Vue: 17 1.想让Vue工作,就必须创建一个Vue实例,且要传入一个配置对象; 18 2.app容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法; 19 3.app容器里的代码被称为【Vue模板】,模板会被vue实例解析成正常的html然后挂载到容器里; 20 4.Vue实例和容器是一一对应的,一对一的关系; 21 5.真实开发中只有一个Vue实例,并且会配合着组件一起使用; 22 6.{{xxx}}中的xxx要写js表达式,且xxx可以自动读取到data中的所有属性; 23 7.一旦data中的数据发生改变,那么页面中用到该数据的地方也会自动更新; 24 25 注意区分:js表达式 和 js代码(语句) 26 1.表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方: 27 (1). a 28 (2). a+b 29 (3). demo(1) 30 (4). x === y ? 'a' : 'b' 31 2.js代码(语句) 32 (1). if(){} 33 (2). for(){} 34 --> 35 36 <!-- 准备好一个容器 --> 37 <div id="app"> 38 <h1>Hello,{{name.toUpperCase()}},{{address}}</h1> 39 </div> 40 41 <script type="text/javascript" > 42 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 43 44 //创建Vue实例 45 //new不可少,Vue本身是个构造函数,不能直接调用,必须通过实例来调用 46 new Vue({ //通过构造函数创建实例 47 el:'#app', //el用于指定当前Vue实例为哪个容器服务,值通常为css选择器字符串。 48 data:{ //data中用于存储数据,数据供el所指定的容器去使用,值我们暂时先写成一个对象。 49 name:'waylon', 50 address:'上海' 51 } 52 }) 53 54 </script> 55 </body> 56 </html>
2、模板语法
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>模板语法</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 11 Vue模板语法有2大类: 12 1.插值语法: 13 功能:用于解析 标签体 内容。 14 写法:{{xxx}},xxx是js表达式,且可以直接读取到data中的所有属性。 15 2.指令语法: 16 功能:用于解析标签(包括:标签属性、标签体内容、绑定事件.....)。 17 举例:v-bind:href="xxx" 或 简写为 :href="xxx",xxx同样要写js表达式, 18 且可以直接读取到data中的所有属性。 19 备注:Vue中有很多的指令,且形式都是:v-????,此处我们只是拿v-bind举个例子。 20 21 --> 22 <!-- 准备好一个容器--> 23 <div id="root"> 24 <h1>插值语法</h1> 25 <h3>你好,{{name}}</h3> 26 <hr/> 27 <h1>指令语法</h1> 28 <!-- 添加v-bind:之后就会把=右边的字符串当成js表达式去执行 --> 29 <a v-bind:href="school.url.toUpperCase()" x="hello">点我去{{school.name}}学习1</a> 30 <a :href="school.url" :x="hello">点我去{{school.name}}学习2</a> 31 </div> 32 </body> 33 34 <script type="text/javascript"> 35 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 36 37 new Vue({ 38 el:'#root', 39 data:{ 40 hello:'嘻嘻', 41 name:'jack', 42 school:{ 43 name:'尚硅谷', //虽然同名,但不同级 44 url:'http://www.atguigu.com', 45 } 46 } 47 }) 48 </script> 49 </html>
3、数据绑定
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>数据绑定</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 11 Vue中有2种数据绑定的方式: 12 1.单向绑定(v-bind):数据只能从data流向页面。 13 2.双向绑定(v-model):数据不仅能从data流向页面,还可以从页面流向data。 14 备注: 15 1.双向绑定一般都应用在表单类元素上(如:input、select等) 16 2.v-model:value 可以简写为 v-model,因为v-model默认收集的就是value值。 17 --> 18 <!-- 准备好一个容器--> 19 <div id="root"> 20 <!-- 普通写法: --> 21 <!-- 22 单向数据绑定:<input type="text" v-bind:value="name"><br/> 23 双向数据绑定:<input type="text" v-model:value="name"><br/> 24 --> 25 26 <!-- 简写: --> 27 单向数据绑定:<input type="text" :value="name"><br/> 28 双向数据绑定:<input type="text" v-model="name"><br/> 29 30 <!-- 如下代码是错误的,因为v-model只能应用在表单类元素(输入类元素)上 --> 31 <!-- <h2 v-model:x="name">你好啊</h2> --> 32 </div> 33 </body> 34 35 <script type="text/javascript"> 36 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 37 38 new Vue({ 39 el:'#root', 40 data:{ 41 name:'尚硅谷' 42 } 43 }) 44 </script> 45 </html>
4、el与data的两种写法
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>el与data的两种写法</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 11 data与el的2种写法 12 1.el有2种写法 13 (1).new Vue时候配置el属性。 14 (2).先创建Vue实例,随后再通过vm.$mount('#root')指定el的值。 15 如果 Vue 实例在实例化时没有收到 el 选项,则它处于“未挂载”状态,没有关联的 DOM 元素。可 16 以使用 vm.$mount() 手动地挂载一个未挂载的实例。 17 2.data有2种写法 18 (1).对象式 19 (2).函数式 20 如何选择:目前哪种写法都可以,以后学习到组件时,data必须使用函数式,否则会报错。 21 3.一个重要的原则: 22 由Vue管理的函数,如data(),一定不要写箭头函数,一旦写了箭头函数,this就不再是Vue实例了,而是Window 23 --> 24 <!-- 准备好一个容器--> 25 <div id="root"> 26 <h1>你好,{{name}}</h1> 27 </div> 28 </body> 29 30 <script type="text/javascript"> 31 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 32 33 //el的两种写法 34 /* 35 const vm = new Vue({ 36 // el:'#root', //第一种写法 37 data:{ 38 name:'尚硅谷' 39 } 40 }) 41 console.log(vm) 42 vm.$mount('#root') //第二种写法,mount意为:挂载 43 */ 44 45 // data的两种写法 46 const vm = new Vue({ 47 el:'#root', 48 //data的第一种写法:对象式 49 /* data:{ 50 name:'尚硅谷' 51 } */ 52 53 //data的第二种写法:函数式 54 data(){ //即data:function(){}的简写 55 console.log('@@@',this) //此处的this是Vue实例对象 56 return{ 57 name:'尚硅谷' 58 } 59 } 60 }) 61 </script> 62 </html>
5、Vue中的MVVM模型
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>理解MVVM</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 11 MVVM模型 12 1. M:模型(Model) :data中的数据 ————>js对象 13 2. V:视图(View) :模板代码 ————>DOM 14 3. VM:视图模型(ViewModel):Vue实例 15 观察发现: 16 1.data中所有的属性,最后都出现在了vm身上。 17 2.vm身上所有的属性 及 Vue原型[Prototype]上所有属性,在Vue模板中都可以直接使用。 18 --> 19 <div id="root"> 20 <h1>学校名称:{{name}}</h1> 21 <h1>学校地址:{{address}}</h1> 22 <!-- <h1>测试一下1:{{1+1}}</h1> 23 <h1>测试一下2:{{$options}}</h1> 24 <h1>测试一下3:{{$emit}}</h1> 25 <h1>测试一下4:{{_c}}</h1> --> 26 </div> 27 </body> 28 29 <script type="text/javascript"> 30 31 const vm = new Vue({ 32 el:'#root', 33 data:{ 34 name:'尚硅谷', 35 address:'北京', 36 } 37 }) 38 console.log(vm) 39 </script> 40 </html>
Vue的实例对象vm:
MVVM在vue中的体现:
6、数据代理
1、关于Object.defineproperty方法
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>关于Object.defineproperty方法</title> 6 </head> 7 <body> 8 <script type="text/javascript"> 9 let number = 18 10 let person = { 11 name:'张三', 12 sex:'男', 13 } 14 15 Object.defineProperty(person,'age',{ 16 // value:18, 17 // enumerable:true, //控制属性是否可以枚举,默认值是false 18 // writable:true, //控制属性是否可以被修改,默认值是false 19 // configurable:true //控制属性是否可以被删除,默认值是false 20 21 //当有人读取person的age属性时,get函数(getter)就会被调用,且返回值就是age的值 22 get(){ 23 console.log('有人读取age属性了') 24 return number 25 }, 26 27 //当有人修改person的age属性时,set函数(setter)就会被调用,且会收到修改的具体值 28 set(value){ 29 console.log('有人修改了age属性,且值是',value) 30 number = value 31 } 32 //getter和setter将person和number两者产生了关联 33 }) 34 // console.log(Object.keys(person)) //将对象的属性名提取出来组成一个数组 35 36 console.log(person) 37 52 </script> 53 </body> 54 </html>
2、何为数据代理?
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>何为数据代理</title> 6 </head> 7 <body> 8 9 <!-- 数据代理:通过一个对象实现对另一个对象中属性的(读/写)操作 --> 10 <script type="text/javascript" > 11 let obj = {x:100} 12 let obj2 = {y:200} 13 14 Object.defineProperty(obj2,'x',{ 15 get(){ 16 return obj.x 17 }, 18 set(value){ 19 obj.x = value 20 } 21 }) 22 </script> 23 </body> 24 </html>
3、在Vue中的数据代理如何实现?
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>Vue中的数据代理</title> 6 <script type="text/javascript" src="js/vue.js"></script> 7 </head> 8 <body> 9 <div id="app"> 10 <h1>个人姓名:{{name}}</h1> 11 <h1>个人年龄:{{age}}</h1> 12 </div> 13 <script type="text/javascript"> 14 const vm = new Vue({ 15 el:"#app", 16 data:{ 17 name:'天青色', 18 age:18 19 } 20 }) 21 </script> 22 </body> 23 </html>
在上面这段代码中,data属性是个对象,可以通过实例对象vm去操作data中的键值对,如下:
这不就是数据代理吗?通过一个对象实现对另一个对象中属性的(读/写)操作 。这点可以从vm实例对象下面的name属性看出来,将鼠标光标移到上面显示 Invoke property getter,表示读取属性值时要通过getter实现。
name和age都是有自己的getter和setter:
其实在vm实例对象下面有个_data属性,里面保存了data里的键值对,可以通过vm._data来进行读写操作:
vm下面的name和age就是通过数据代理与_data中的name和age建立了联系,如果没有这层联系,那模板中{{name}}就不能直接拿到_data中的name了,而应该是{{ _data.name }}才可以。而_data数据又来自于data,所以vm就很方便的代理操作了data。
尚硅谷老师的图也讲得很清楚:
补充一点,_data里还实现了数据劫持。当我们通过vm.name更改值时,页面上用到name的地方也会自动响应式更新了。这就是_data里数据劫持的作用。
总结:
1.Vue中的数据代理:
通过vm对象来代理data对象中属性的操作(读/写)
2.Vue中数据代理的好处:
更加方便的操作data中的数据
3.基本原理:
通过Object.defineProperty()把data对象中所有属性添加到vm上。
为每一个添加到vm上的属性,都指定一个getter/setter。
在getter/setter内部去操作(读/写)data中对应的属性。
7、事件处理
8、计算属性
先实现一个小案例:
输入框默认有张和三,手动输入后全名也会跟着改变。
1、通过插值语法实现案例
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>姓名案例_插值语法实现</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 准备好一个容器--> 11 <div id="root"> 12 姓:<input type="text" v-model="firstName"> <br/><br/> 13 名:<input type="text" v-model="lastName"> <br/><br/> 14 全名:<span>{{firstName}}-{{lastName}}</span> 15 </div> 16 </body> 17 18 <script type="text/javascript"> 19 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 20 21 new Vue({ 22 el:'#root', 23 data:{ 24 firstName:'张', 25 lastName:'三' 26 } 27 }) 28 </script> 29 </html>
2、通过methods实现案例
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>姓名案例_methods实现</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 准备好一个容器--> 11 <div id="root"> 12 姓:<input type="text" v-model="firstName"> <br/><br/> 13 名:<input type="text" v-model="lastName"> <br/><br/> 14 全名:<span>{{fullName()}}</span> 15 </div> 16 </body> 17 18 <script type="text/javascript"> 19 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 20 21 new Vue({ 22 el:'#root', 23 data:{ 24 firstName:'张', 25 lastName:'三' 26 }, 27 methods: { 28 fullName(){ 29 console.log('@---fullName') 30 return this.firstName + '-' + this.lastName 31 } 32 }, 33 }) 34 </script> 35 </html>
注意14行的{{fullName()}}是要加()的。
另外,由于是双向数据绑定,每次输入都会导致data对象里面的属性值发生改变,从而会使得模板代码被Vue重新渲染,fullName方法也会被重新调用。如下:
3、通过计算属性实现案例
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>姓名案例_计算属性实现</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 21 <!-- 准备好一个容器--> 22 <div id="root"> 23 姓:<input type="text" v-model="firstName"> <br/><br/> 24 名:<input type="text" v-model="lastName"> <br/><br/> 25 测试:<input type="text" v-model="x"> <br/><br/> 26 全名:<span>{{fullName}}</span> <br/><br/> 27 <!-- 全名:<span>{{fullName}}</span> <br/><br/> 28 全名:<span>{{fullName}}</span> <br/><br/> 29 全名:<span>{{fullName}}</span> --> 30 </div> 31 </body> 32 33 <script type="text/javascript"> 34 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 35 36 const vm = new Vue({ 37 el:'#root', 38 data:{ 39 firstName:'张', 40 lastName:'三', 41 x:'你好' 42 }, 43 methods: { 44 demo(){ 45 46 } 47 }, 48 computed:{ 49 fullName:{ 50 //get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值 51 //get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。 52 get(){ 53 console.log('get被调用了') 54 // console.log(this) //经过Vue的处理后此处的this是vm 55 return this.firstName + '-' + this.lastName 56 }, 57 //set什么时候调用? 当fullName被修改时。 58 set(value){ 59 console.log('set',value) 60 const arr = value.split('-') 61 this.firstName = arr[0] 62 this.lastName = arr[1] 63 } 64 } 65 } 66 }) 67 </script> 68 </html>
总结:
1.定义:要用的属性不存在,要通过已有属性(如data对象里的属性)计算得来。它也是vm下面的一个属性。
2.原理:底层借助了Objcet.defineproperty方法提供的getter和setter。
3.get函数什么时候执行?
(1).初次读取时会执行一次。
(2).当依赖的数据发生改变时会被再次调用。
4.优势:与methods实现相比,内部有缓存机制(复用),效率更高,调试方便。
5.计算属性最终会出现在vm上,直接插值法读取使用即可。
6.如果计算属性要被修改,那必须写set函数去响应修改,且set中要引起计算时依赖的数据发生改变。
4、计算属性的简写
当只考虑计算属性的读取不考虑修改的时候,就可以简写:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>姓名案例_计算属性实现</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 准备好一个容器--> 11 <div id="root"> 12 姓:<input type="text" v-model="firstName"> <br/><br/> 13 名:<input type="text" v-model="lastName"> <br/><br/> 14 全名:<span>{{fullName}}</span> <br/><br/> 15 </div> 16 </body> 17 18 <script type="text/javascript"> 19 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 20 21 const vm = new Vue({ 22 el:'#root', 23 data:{ 24 firstName:'张', 25 lastName:'三', 26 }, 27 computed:{ 28 //完整写法 29 /* fullName:{ 30 get(){ 31 console.log('get被调用了') 32 return this.firstName + '-' + this.lastName 33 }, 34 set(value){ 35 console.log('set',value) 36 const arr = value.split('-') 37 this.firstName = arr[0] 38 this.lastName = arr[1] 39 } 40 } */ 41 //简写 42 fullName(){ 43 console.log('get被调用了') 44 return this.firstName + '-' + this.lastName 45 } 46 } 47 }) 48 </script> 49 </html>
读取的时候依然是 {{计算属性}} ,不可加() 。
9、监视属性
实现天气小案例:
默认炎热,点击后切换为凉爽,再点击切换为炎热。
1、实现案例
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title></title> 6 <script type="text/javascript" src="js/vue.js"></script> 7 </head> 8 <body> 9 <div id="app"> 10 <h1>今天的天气很{{weather}}</h1> 11 <button type="button" @click="changeWeather">点我切换天气</button> 12 <!-- <button type="button" @click="ishot=!ishot;x其他代码x">点我切换天气</button> --> 13 <!-- <button type="button" @click="window.alert('点击成功')">点我切换天气</button> --> 14 <!-- 在绑定事件的时候,@xxx='yyy',这里的yyy可以写一些简单的语句,复杂的话就交给methods --> 15 </div> 16 <script type="text/javascript"> 17 const vm = new Vue({ 18 el:'#app', 19 data:{ 20 ishot:true, 21 // window 点击事件里的window在vm里找不到,所以要在这添加window,不然会报错 22 }, 23 methods:{ 24 changeWeather(){ 25 this.ishot = !this.ishot 26 } 27 }, 28 computed:{ 29 weather(){ 30 return this.ishot ? '炎热' : '凉爽' 31 } 32 } 33 }) 34 </script> 35 </body> 36 </html>
2、监视属性watch
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>天气案例_监视属性</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 准备好一个容器--> 11 <div id="root"> 12 <h2>今天天气很{{info}}</h2> 13 <button @click="changeWeather">切换天气</button> 14 </div> 15 </body> 16 17 <script type="text/javascript"> 18 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 19 20 const vm = new Vue({ 21 el:'#root', 22 data:{ 23 isHot:true, 24 }, 25 computed:{ 26 info(){ 27 return this.isHot ? '炎热' : '凉爽' 28 } 29 }, 30 methods: { 31 changeWeather(){ 32 this.isHot = !this.isHot 33 } 34 }, 35 /* watch:{ 36 isHot:{ 37 immediate:true, //初始化时让handler调用一下 38 //handler什么时候调用?当isHot发生改变时。 39 handler(newValue,oldValue){ 40 console.log('isHot被修改了',newValue,oldValue) 41 } 42 } 43 } */ 44 }) 45 46 vm.$watch('isHot',{ 47 immediate:true, //初始化时让handler调用一下 48 //handler什么时候调用?当isHot发生改变时。 49 handler(newValue,oldValue){ 50 console.log('isHot被修改了',newValue,oldValue) 51 } 52 }) 53 </script> 54 </html>
总结:
监视属性watch:
1.当被监视的属性变化时, 回调函数自动调用, 进行相关操作
2.监视的属性必须存在,才能进行监视!可以使data里的属性,也可以是计算属性
3.监视的两种写法:
(1).new Vue时传入watch配置(初期明确知道需要监视)
(2).通过vm.$watch监视(后期需求添加的监视)
3、深度监视deep
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>天气案例_深度监视</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 准备好一个容器--> 11 <div id="root"> 12 <h2>今天天气很{{info}}</h2> 13 <button @click="changeWeather">切换天气</button> 14 <hr/> 15 <h3>a的值是:{{numbers.a}}</h3> 16 <button @click="numbers.a++">点我让a+1</button> 17 <h3>b的值是:{{numbers.b}}</h3> 18 <button @click="numbers.b++">点我让b+1</button> 19 <button @click="numbers = {a:666,b:888}">彻底替换掉numbers</button> 20 <!-- {{numbers.c.d.e}} --> 21 </div> 22 </body> 23 24 <script type="text/javascript"> 25 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 26 27 const vm = new Vue({ 28 el:'#root', 29 data:{ 30 isHot:true, 31 numbers:{ 32 a:1, 33 b:1, 34 c:{ 35 d:{ 36 e:100 37 } 38 } 39 } 40 }, 41 computed:{ 42 info(){ 43 return this.isHot ? '炎热' : '凉爽' 44 } 45 }, 46 methods: { 47 changeWeather(){ 48 this.isHot = !this.isHot 49 } 50 }, 51 watch:{ 52 isHot:{ 53 // immediate:true, //初始化时让handler调用一下 54 //handler什么时候调用?当isHot发生改变时。 55 handler(newValue,oldValue){ 56 console.log('isHot被修改了',newValue,oldValue) 57 } 58 }, 59 //监视多级结构中某个属性的变化,注意要用引号,之前isHot是简写 60 /* 'numbers.a':{ 61 handler(){ 62 console.log('a被改变了') 63 } 64 } */ 65 //监视多级结构中所有属性的变化 66 numbers:{ 67 deep:true, //默认为false,开启深度监视 68 handler(){ 69 console.log('numbers改变了') 70 } 71 } 72 } 73 }) 74 75 </script> 76 </html>
总结:
深度监视:
(1).Vue中的watch默认不监测对象内部值的改变(一层)。
(2).配置deep:true可以监测对象内部值改变(多层)。
(3).Vue自身可以监测对象内部值的改变,无论有多少层,如numbers.c.d.e,但Vue提供的watch默认不可以!
(4).考虑到效率性,使用watch时根据数据的具体结构,决定是否采用深度监视。
4、监视属性简写
当监视某个属性而不需要配置immediate和deep时,可以使用简写形式,类似于计算属性的简写:
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="UTF-8" /> 5 <title>天气案例_监视属性_简写</title> 6 <!-- 引入Vue --> 7 <script type="text/javascript" src="js/vue.js"></script> 8 </head> 9 <body> 10 <!-- 准备好一个容器--> 11 <div id="root"> 12 <h2>今天天气很{{info}}</h2> 13 <button @click="changeWeather">切换天气</button> 14 </div> 15 </body> 16 17 <script type="text/javascript"> 18 Vue.config.productionTip = false //阻止 vue 在启动时生成生产提示。 19 20 const vm = new Vue({ 21 el:'#root', 22 data:{ 23 isHot:true, 24 }, 25 computed:{ 26 info(){ 27 return this.isHot ? '炎热' : '凉爽' 28 } 29 }, 30 methods: { 31 changeWeather(){ 32 this.isHot = !this.isHot 33 } 34 }, 35 watch:{ 36 //正常写法 37 /* isHot:{ 38 // immediate:true, //初始化时让handler调用一下 39 // deep:true,//深度监视 40 handler(newValue,oldValue){ 41 console.log('isHot被修改了',newValue,oldValue) 42 } 43 }, */ 44 //简写 45 /* isHot(newValue,oldValue){ 46 console.log('isHot被修改了',newValue,oldValue,this) 47 } */ 48 } 49 }) 50 51 //正常写法 52 /* vm.$watch('isHot',{ 53 immediate:true, //初始化时让handler调用一下 54 deep:true,//深度监视 55 handler(newValue,oldValue){ 56 console.log('isHot被修改了',newValue,oldValue) 57 } 58 }) */ 59 60 //简写 61 /* vm.$watch('isHot',(newValue,oldValue)=>{ 62 console.log('isHot被修改了',newValue,oldValue,this) 63 }) */ 64 65 </script> 66 </html>
11