Vue(Vue2+Vue3)——12.监视属性(watch)

简介: Vue(Vue2+Vue3)——12.监视属性(watch)

12 监视属性(watch)


可以先使用技术属性的方式编写天气案例,然后使用监视属性,通过对比,更加清晰明了


12.1 编写案例


我们可以使用三木运算符实现对天气的更换,如果属性为真就是炎热,为假就是寒冷

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>初始vue</title>
    <!-- 引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- 三元表达式 -->
        <h2>今天天气很{{isHot ? '炎热':'寒冷'}}</h2>
        <button>点击切换天气</button>
    </div> 
    <script type="text/javascript">
        //Vue.config.keyCodes.huiche=13 // 定义了一个叫huiche的别名按键,这个按键对应的键码是13,也就是enter回车键
        const vm=new Vue({
            el:'#root',
            data:{
                //布尔值,如果为真就是天气热,为假就是天气冷
                isHot:true
            }
        }) 
    </script>
</body>
</html>

但是不建议在插值语法里面做复杂操作,可以使用技术属性操作,利用插值语法获取计算属性的结果


12.2 计算属性完善案例


使用计算属性完善案例,同时给按钮绑定单击事件去升级案例改变天气

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>初始vue</title>
    <!-- 引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <!-- 三元表达式 -->
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换天气</button>
    </div> 
    <script type="text/javascript">
        //Vue.config.keyCodes.huiche=13 // 定义了一个叫huiche的别名按键,这个按键对应的键码是13,也就是enter回车键
        const vm=new Vue({
            el:'#root',
            data:{
                //布尔值,如果为真就是天气热,为假就是天气冷
                isHot:true
            },
            computed:{
                info(){
                    return this.isHot?'炎热':'寒冷'
                }
            },
            methods: {
                changeWeather(){
                    // 直接两极反转
                    this.isHot=!this.isHot
                }
            },
        }) 
    </script>
</body>
</html>

代码到这对于这个案例基本就写完了,但是我想分享一个坑和一个使用技巧


12.3 坑


我们改下代码,注意看,现在已经不用info这个计算属性和isHot这个属性了

我们单击按钮,发现vue开发工具对应的数据并没有改变,其实已经改变了,只是它觉得既然页面上已经没有用到这些改变数据的地方了,那么它就没必要更新了,反正它更新你也不用

通过控制台验证数据已经更新

这个问题也不严重,只是目前存在,说不定某天版本迭代就把这个坑填上了,只是希望大家知道这个坑!


12.4 使用技巧


注意观察代码和案例,按钮只想做一件事,就是更改属性的值,那么我就不需要写那么多的代码去做一个简单的事情,而是把逻辑都写在单击事件里面

效果也是一样的,但是要说明下,如果事件的逻辑很简单只有一件事,这样写没有问题,如果有多个事,需要用;分开,比如:

<button @click="isHot=!isHot;a++">点击切换天气</button>

如果有多个逻辑需要处理,那么还是建议写在函数里面


12.5 监视属性完成案例


在原有的技术上,通过监视属性的方式完成案例,监视isHot属性的变化,如果改变了,就要通知我,由我执行对应的逻辑,有两种监视方式,一一说明


监视方式1 直接使用watch


vue中通过watch实现监视,有一个handler函数,如果我们对监视属性的值进行修改的时候就会被调用,handler有两个参数,分别是修改前的值和修改后的值

还有一个函数叫immediate,默认为false,如果设置为true表示初始化时候让handler调用一下

我还没点击呢就自己调用了,还有更多的函数就不一一列举了

不只是可以监视data中的属性,也可以监视computed里面的计算属性

相关代码

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>初始vue</title>
    <!-- 引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换天气</button>
    </div> 
    <script type="text/javascript">
        //Vue.config.keyCodes.huiche=13 // 定义了一个叫huiche的别名按键,这个按键对应的键码是13,也就是enter回车键
        const vm=new Vue({
            el:'#root',
            data:{
                //布尔值,如果为真就是天气热,为假就是天气冷
                isHot:true
            },
            computed:{
                info(){
                    return this.isHot?'炎热':'寒冷'
                }
            },
            methods: {
                changeWeather(){
                    // 直接两极反转
                    this.isHot=!this.isHot
                }
            },
           // 第一种监视方式
             watch:{
                isHot:{
                        immediate:true, //初始化时候让handler调用一下
                        // handler什么时候被调用? 当isHot发生改变时,就会发生调用 有两个参数,分别是修改前的值和修改后的值
                       handler(newValue,oldValue){
                      console.log('isHot被修改了',newValue,oldValue)
                   }
              }
              }
        })
    </script>
</body>
</html>


监视方式2 使用$watch()


<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>初始vue</title>
    <!-- 引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换天气</button>
    </div> 
    <script type="text/javascript">
        //Vue.config.keyCodes.huiche=13 // 定义了一个叫huiche的别名按键,这个按键对应的键码是13,也就是enter回车键
        const vm=new Vue({
            el:'#root',
            data:{
                //布尔值,如果为真就是天气热,为假就是天气冷
                isHot:true
            },
            computed:{
                info(){
                    return this.isHot?'炎热':'寒冷'
                }
            },
            methods: {
                changeWeather(){
                    // 直接两极反转
                    this.isHot=!this.isHot
                }
            },
           // 第一种监视方式
            // watch:{
            //     isHot:{
            //         immediate:true, //初始化时候让handler调用一下
            //         // handler什么时候被调用? 当isHot发生改变时,就会发生调用 有两个参数,分别是修改前的值和修改后的值
            //         handler(newValue,oldValue){
            //             console.log('isHot被修改了',newValue,oldValue)
            //         }
            //     }
            // }
        })
         // 第二种监视方式 
         vm.$watch('isHot',{
                immediate:true, //初始化时候让handler调用一下
                // handler什么时候被调用? 当isHot发生改变时,就会发生调用 有两个参数,分别是修改前的值和修改后的值
                handler(newValue,oldValue){
                     console.log('isHot被修改了',newValue,oldValue)
                }
         })
    </script>
</body>
</html>


两种监视方式如何选择


如果很明确的知道需要监视哪个属性,那么直接使用方式1的watch监视比较合适,如果说不知道要检测谁,后续根据用户的行为才知道检测谁,那么方式2使用$watch无疑是更好的


12.6 总结watch


监视属性watcher:

1 当被监视的属性发生变化时,回调函数自动调用,进行相关逻辑处理

2 监视的属性必须存在,才能进行监视

  • 3 监视的两种写法:
  •  (1).new Vue时传入watch配置
  •  (2)通过vm.$watch监视


12.7 深度监视


在监视属性的技术上,再学习深入的深度监视,还是天气的案例,再次基础上加一个新的功能

接下来提出需求,我想要监视a的变化,我们如果直接写number,a的话会报错,因为这个key是错误格式的,所以面对这种情况,我们需要还原成原始key的写法,也就是'number.a',这种写法适用于多级属性结构

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>初始vue</title>
    <!-- 引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换天气</button>
        <hr/>
        <h2>a的值是:{{number.a}}</h2>
        <button @click='number.a++'>点我让a自增</button>
        <hr/>
        <h2>b的值是:{{number.b}}</h2>
        <button @click='number.b++'>点我让b自增</button>
    </div> 
    <script type="text/javascript">
        //Vue.config.keyCodes.huiche=13 // 定义了一个叫huiche的别名按键,这个按键对应的键码是13,也就是enter回车键
        const vm=new Vue({
            el:'#root',
            data:{
                //布尔值,如果为真就是天气热,为假就是天气冷
                isHot:true,
                number:{
                    a:1,
                    b:1
                }
            },
            computed:{
                info(){
                    return this.isHot?'炎热':'寒冷'
                }
            },
            methods: {
                changeWeather(){
                    // 直接两极反转
                    this.isHot=!this.isHot
                }
            },
            watch:{
                //监视多级结构中某个属性的变化
                'number.a':{
                    immediate:true, //初始化时候让handler调用一下
                    handler(newValue,oldValue){
                        console.log('a被修改了',newValue,oldValue)
                    }
                }
            }
        })
    </script>
</body>
</html>

如果我想要监视属性b呢?

我一开始想到的笨办法是,复制a的监视改为b,但是如果number里面如果有成千上万个数据呢。。

不如直接监视number,并且配置一个新的属性:deep(有深度的),默认false,改为true就表示深度监视对象的每一个属性变化

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>初始vue</title>
    <!-- 引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换天气</button>
        <hr/>
        <h2>a的值是:{{number.a}}</h2>
        <button @click='number.a++'>点我让a自增</button>
        <hr/>
        <h2>b的值是:{{number.b}}</h2>
        <button @click='number.b++'>点我让b自增</button>
    </div> 
    <script type="text/javascript">
        //Vue.config.keyCodes.huiche=13 // 定义了一个叫huiche的别名按键,这个按键对应的键码是13,也就是enter回车键
        const vm=new Vue({
            el:'#root',
            data:{
                //布尔值,如果为真就是天气热,为假就是天气冷
                isHot:true,
                number:{
                    a:1,
                    b:1
                }
            },
            computed:{
                info(){
                    return this.isHot?'炎热':'寒冷'
                }
            },
            methods: {
                changeWeather(){
                    // 直接两极反转
                    this.isHot=!this.isHot
                }
            },
            watch:{
                 //监视多级结构中某个属性的变化
               /*   'number.a':{
                    immediate:true, //初始化时候让handler调用一下
                    handler(newValue,oldValue){
                        console.log('a被修改了',newValue,oldValue)
                    }
                } */
                //监视多级结构中所有属性的变化
                number:{
                    deep:true, //开启深度监视
                    immediate:true, //初始化时候让handler调用一下
                    handler(newValue,oldValue){
                        console.log('number被修改了',newValue,oldValue)
                    }
                }
            }
        })
    </script>
</body>
</html>

12.8 总结深度监视

深度监视:

(1)vue中的watch默认不监测对象内部值的改变(一层)

(2)配置deep:true可以监测对象内部值改变(多层)

备注:

(1)vue自身可以监测对象内部值的改变,但vue提供的watch默认

(2)使用watch时根据数据的具体结构,决定是否采用深度监视


12.9 监视的简写形式


watch简写


监视是可以简写的,但是有两个前提:

1 不需要immediate(初始化调用)

2 不需要deep(深度监视)

也就是说当配置项只有handler的时候,就可以开启简写形式

写法如下:

效果也是一样的


$watch的简写


友情提示:函数要用普通函数去写,不能使用箭头函数,不然this就不是vue实例对象了

完整代码如下

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>初始vue</title>
    <!-- 引入vue.js -->
    <script type="text/javascript" src="../js/vue.js"></script>
</head>
<body>
    <div id="root">
        <h2>今天天气很{{info}}</h2>
        <button @click="changeWeather">点击切换天气</button>
    </div> 
    <script type="text/javascript">
        //Vue.config.keyCodes.huiche=13 // 定义了一个叫huiche的别名按键,这个按键对应的键码是13,也就是enter回车键
        const vm=new Vue({
            el:'#root',
            data:{
                //布尔值,如果为真就是天气热,为假就是天气冷
                isHot:true
            },
            computed:{
                info(){
                    return this.isHot?'炎热':'寒冷'
                }
            },
            methods: {
                changeWeather(){
                    // 直接两极反转
                    this.isHot=!this.isHot
                }
            },
            watch:{
                // 正常写法
               /*  isHot:{
                    immediate:true, //初始化时候让handler调用一下
                    // handler什么时候被调用? 当isHot发生改变时,就会发生调用 有两个参数,分别是修改前的值和修改后的值
                    handler(newValue,oldValue){
                        console.log('isHot被修改了',newValue,oldValue)
                    }
                } */
                // 简写写法
               /*  isHot(newValue,oldValue){
                        console.log('isHot被修改了',newValue,oldValue)
                } */
            }
        })
        // $watch正常格式
        /*   vm.$watch('isHot',{
            immediate:true, //初始化时候让handler调用一下
                    // handler什么时候被调用? 当isHot发生改变时,就会发生调用 有两个参数,分别是修改前的值和修改后的值
                    handler(newValue,oldValue){
                        console.log('isHot被修改了',newValue,oldValue)
                    }
          }) */
            // $watch简写格式
            vm.$watch('isHot',function(newValue,oldValue){
                console.log('isHot被修改了',newValue,oldValue)
            })
    </script>
</body>
</html>


12.10 computed和watch之前的区别


  •  computed和watch之前的区别
  •  1 computed能够完成的功能,watch都能完成
  •  2 watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作
  •  两个重要的小原则:
  •  1 所被vue管理的函数,最好都写成普通函数,这样this指向的才是vue实例对象
  •  2 所有不被vue所管理的函数(定时器的回调函数,ajax的回调函数等),最好都写成箭头函数,这样this指向的才是vm或组件实例对象
相关文章
|
2天前
|
JavaScript 前端开发 开发者
VUE学习一:初识VUE、指令、动态绑定、计算属性
这篇文章主要介绍了Vue.js的基础知识,包括初识Vue、指令如v-for、v-on的使用、动态属性绑定(v-bind)、计算属性等概念与实践示例。
13 1
|
5天前
|
缓存 JavaScript 前端开发
探索Vue.js中的计算属性与侦听器
【10月更文挑战第5天】探索Vue.js中的计算属性与侦听器
11 1
|
5天前
|
缓存 JavaScript 前端开发
深入理解Vue.js中的计算属性与侦听属性
【10月更文挑战第5天】深入理解Vue.js中的计算属性与侦听属性
10 0
|
JavaScript 测试技术 容器
Vue2+VueRouter2+webpack 构建项目
1). 安装Node环境和npm包管理工具 检测版本 node -v npm -v 图1.png 2). 安装vue-cli(vue脚手架) npm install -g vue-cli --registry=https://registry.
1040 0
|
3天前
|
JavaScript 数据可视化
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
这篇文章介绍了如何使用vue-cli 2和3版本来创建Vue项目,并详细说明了两者之间的主要区别。
23 5
vue-cli学习一:vue脚手架的 vue-cli2和vue-cli3版本 创建vue项目,vue的初始化详解
|
2天前
|
存储 JavaScript 前端开发
Vue中组件通信方式有哪些?
本文介绍了 Vue 中几种常见的组件间通信方式,包括 Props / $emit、provide / inject、ref / refs、eventBus、Vuex、$parent / $children、$attrs / $listeners 以及通过 vue-router 传参。每种方式都有其适用场景和注意事项,帮助开发者根据具体需求选择合适的通信方式。
10 3
Vue中组件通信方式有哪些?
|
2天前
|
JavaScript
VUE学习二:事件监听(v-on)、条件判断(v-if/v-else-if/v-else)、循环遍历(v-for)
这篇文章是关于Vue.js的学习指南,涵盖了事件监听、条件判断、循环遍历、数组方法响应性、案例分析以及高阶函数的使用。
14 2
VUE学习二:事件监听(v-on)、条件判断(v-if/v-else-if/v-else)、循环遍历(v-for)
|
3天前
|
JavaScript 数据可视化
vue-cli学习二:vue-cli3版本 创建vue项目后,Runtime-Compiler和Runtime-only两个模式详解;vue项目管理器;配置文件的配置在哪,以及如何配置
这篇文章详细介绍了Vue CLI 3版本创建项目时的Runtime-Compiler和Runtime-only两种模式的区别、Vue程序的运行过程、render函数的使用、eslint的关闭方法,以及Vue CLI 2和3版本配置文件的不同和脚手架3版本创建项目的配置文件配置方法。
13 3
vue-cli学习二:vue-cli3版本 创建vue项目后,Runtime-Compiler和Runtime-only两个模式详解;vue项目管理器;配置文件的配置在哪,以及如何配置
|
1天前
|
JavaScript
vue 函数化组件
【10月更文挑战第1天】 Vue.js 的函数化组件通过设置 `functional: true`,使其无状态和无实例,从而减少渲染开销。通过 `render` 函数的 `context` 参数传递数据。示例中,`smart-item` 组件根据 `data.type` 动态选择并渲染 `ImgItem`、`VideoItem` 或 `TextItem` 组件。根实例 `app` 通过按钮切换不同类型的组件数据。函数化组件适用于程序化选择组件和操作传递数据的场景。
|
1天前
|
JavaScript 开发者
vue指令的开发看这篇文章就够了!超详细,赶快收藏!
【10月更文挑战第8天】vue指令的开发看这篇文章就够了!超详细,赶快收藏!
vue指令的开发看这篇文章就够了!超详细,赶快收藏!