第5集丨Vue 江湖 —— 监视属性/侦听属性

news2024/11/13 12:58:54

目录

  • 一、基本使用
    • 1.1 watch配置监视
    • 1.2 vm.$watch动态监视
    • 1.3 深度监视(deep watch)
    • 1.4 简写形式
  • 二、computed和watch的对比
    • 2.1 使用watch实现setTimeout操作
    • 2.2 用computed无法实现setTimeout
  • 三、其他注意事项
    • 3.1 vue devtools的bug
    • 3.2 @xxx=yyy格式
    • 3.3 将window传入data中

Vue 提供了一种更通用的方式来观察和响应 Vue实例上的数据变动:侦听属性,也成为监视属性

一、基本使用

监视属性watch:

  1. 当被监视的属性变化时,回调函数handler自动调用,进行相关操作。
  2. 监视的属性必须存在,才能进行监视。
  3. 监视的两种写法
    a. new Vue时传入watch配置
    b. 通过vm.$watch来动态实现监视

1.1 watch配置监视

下面案例中,我们通过watch配置属性来给isHuoguo 添加监视,当isHuoguo发生变化时,所配置的handler()函数会调用。

注意:这里有一个属性immediate,其默认值为false。当配置为true时,页面初始化时,让handler调用一下。

<div id="root">
    <h2>今天我们去吃{{info}}</h2>
    <button @click="change">切换</button>
</div>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            isHuoguo:true
        },
        computed:{
            info() {
                return this.isHuoguo?'火锅':'南京大排档';
            }
        },
        methods: {
            change() {
                this.isHuoguo = !this.isHuoguo;
            }
        },
        watch: {
            isHuoguo:{
                immediate:true,//默认为false,初始化时,让handler调用一下。
                handler(newValue, oldValue) {
                    console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);
                }
            }
        }
    })
</script>

效果图如下:

在这里插入图片描述

1.2 vm.$watch动态监视

不仅可以给属性(即data中定义的)添加监视,也可以给计算属性添加监视。

下面例子,我们通过vm.$watch 方式,来动态给计算属性info添加监视:

<div id="root">
    <h2>今天我们去吃{{info}}</h2>
    <button @click="change">切换</button>
</div>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            isHuoguo:true
        },
        computed:{
            info() {
                return this.isHuoguo?'火锅':'南京大排档';
            }
        },
        methods: {
            change() {
                this.isHuoguo = !this.isHuoguo;
            }
        },
        watch: {
            isHuoguo:{
                // immediate:true,//默认为false,初始化时,让handler调用一下。
                handler(newValue, oldValue) {
                    console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);
                }
            }
        }
    })

    // 监视计算属性
    vm.$watch('info',{
        // immediate:true,//默认为false,初始化时,让handler调用一下。
        handler(newValue, oldValue) {
            console.log("info计算属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);
        }
    })

</script>

在这里插入图片描述

1.3 深度监视(deep watch)

深度监视(deep watch):

  1. Vue中的watch默认不监测对象内部值的改变(只监测一层结构)
  2. 配置deep:true可以监测对象内部值的改变(可以监测多层结构),Vue默认不开启deep,是为了提供效率。
  3. Vue自身可以监测对象内部值的改变,但是Vue提供的watch默认不可以。
  4. 使用watch时,要根据数据的具体结构,决定是否采用深度监视。

使用方式:

  • 监视多级结构中某个属性的变化,例如下面例子中numbers.a
  • 监视多级结构中所有属性的变化,numbers:{deep:true,handler(){}}
<div id="root">
    <h3>今天我们去吃{{info}}</h3>
    <button @click="change">切换</button>
    <hr>
    <h3>a的值是{{numbers.a}}</h3>
    <button @click="numbers.a++">点击a++</button>
    <hr>
    <h3>b的值是{{numbers.b}}</h3>
    <button @click="numbers.b++">点击b++</button>
</div>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            isHuoguo:true,
            numbers:{
                a:1,
                b:1
            }
        },
        computed:{
            info() {
                return this.isHuoguo?'火锅':'南京大排档';
            }
        },
        methods: {
            change() {
                this.isHuoguo = !this.isHuoguo;
            }
        },
        watch: {
            isHuoguo:{
                handler(newValue, oldValue) {
                    console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);
                }
            },
            // 监视多级结构中某个属性的变化
            "numbers.a": {
                handler() {
                    console.log("a被改变了!");
                }
            },
            // 监视多级结构中所有属性的变化
            numbers:{
                deep:true,
                handler() {
                    console.log("numbers改变了!");
                }
            }
            
        }
    })

   
</script>

1.4 简写形式

当所配置的监视,只需要handler,不需要其他配置的时候,才可以使用简写形式,使用函数来代替。

两类简写形式:

  • watch配置里的简写
  • 动态添加监视的简写
<div id="root">
    <h3>今天我们去吃{{info}}</h3>
    <button @click="change">切换</button>
</div>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            isHuoguo:true
        },
        computed:{
            info() {
                return this.isHuoguo?'火锅':'南京大排档';
            }
        },
        methods: {
            change() {
                this.isHuoguo = !this.isHuoguo;
            }
        },
        watch: {
            /* isHuoguo:{
                deep:true,
                immediate:true,
                handler(newValue, oldValue) {
                    console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);
                }
            }, */
            // 简写形式
            isHuoguo(newValue, oldValue) {
                
                console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);
            }
        }
    })

    // 动态添加监视的简写
    vm.$watch('isHuoguo',function(newValue, oldValue){
        console.log("isHuoguo属性被修改了,newValue:"+newValue+",oldValue:"+oldValue);
    })
   
</script>

二、computed和watch的对比

计算属性(computed)和监视属性(watch)之间的区别:

  1. computed能完成的功能,watch都可以完成
  2. watch能完成的功能,computed不一定能完成,例如:watch可以进行异步操作。

两个重要的原则
3. 被Vue所管理的函数,最好写成普通函数,这样this的指向才是vm组件实例对象
4. 所有不被Vue管理的函数(定时器的回调函数(setTimeout)、ajax的回调函数、Promise的回调函数等),最好写成箭头函数,这样this的指向才是 vm组件实例对象

2.1 使用watch实现setTimeout操作

下面代码,使用了watch实现setTimeout操作,有一点需要注意的是,setTimeout所指定的回调函数要使用箭头函数(因为箭头函数本身没有this),否则this指向window了,而不再是vm实例。

<div id="root">
    <div class="row">姓:<input type="text" v-model="firstName"></div>
    <div class="row">名:<input type="text" v-model="lastName"></div>
    <div class="row">全名:<span>{{fullName}}</span></div>
</div>

<script>
    const vm = new Vue({
        el:'#root',
        data() {
            return {
                firstName: '小',
                lastName: '三',
                fullName:'小-三'
            };
        },
        methods:{
            
        },
        watch:{
            firstName(val) {
                setTimeout(() => {  //这里不能写成普通函数,否则this指向window了
                    console.log(this);  //vm实例对象
                    this.fullName = val + "-" + this.lastName;
                }, 1000);
                
            },
            lastName(val){
                this.fullName = this.firstName + "-" + val;
            }
        }
    });
</script>

2.2 用computed无法实现setTimeout

computed计算属性,无法实现setTimeout想要的功能,如下错误代码所示:

<div id="root">
    <div class="row">姓:<input type="text" v-model="firstName"></div>
    <div class="row">名:<input type="text" v-model="lastName"></div>
    <div class="row">全名:<span>{{fullName}}</span></div>
    
</div>

<script>
    const vm = new Vue({
        el:'#root',
        // 对于Vue来说,data中配置的就是属性。
        // 计算属性:用现有的属性去加工、计算生成一个全新的属性。和属性分开放
        data:{
            firstName: '小',
            lastName: '三'
        },
        computed:{
            fullName() {
                console.log('get被调用了!');
                // console.log(this);
                setTimeout(() => {
                    return this.firstName+'-'+this.lastName
                }, 1000);
                
            }
        }
        
    });
</script>

三、其他注意事项

3.1 vue devtools的bug

当页面上没有用到某个计算属性时,vue devtools调试工具会出现一个bug:不会显示数据的变化了。例如下面代码

<div id="root">
    <h2>今天我们去吃米饭</h2>
    <button @click="change">切换</button>
</div>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            isHuoguo:true
        },
        computed:{
            info() {
                return this.isHuoguo?'火锅':'南京大排档';
            }
        },
        methods: {
            change() {
                this.isHuoguo = !this.isHuoguo;
            }
        },
    })
</script>

点击切换按钮,工具中显示的datacomputed 不发生变化,其实数据已经发生了改变。可以通过控制台中输入vm.info来查看。如下图所示:

在这里插入图片描述
在这里插入图片描述

3.2 @xxx=yyy格式

这里的yyy不是事件名称,而是一些简单的语句。例如:@click="isHuoguo = !isHuoguo;count++;"

下面的案例中,两个按钮均可实现功能。不过需要注意的是,执行语句比较复杂的时候不建议直接写在yyy中。

<div id="root">
    <h2>今天我们去吃{{info}}--切换次数{{count}}</h2>
    <button @click="change">切换</button>
    <button @click="isHuoguo = !isHuoguo;count++">切换2</button>
</div>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            isHuoguo:true,
            count:0,
        },
        computed:{
            info() {
                return this.isHuoguo?'火锅':'南京大排档';
            }
        },
        methods: {
            change() {
                this.count++;
                this.isHuoguo = !this.isHuoguo;
            }
        },
    })
</script>

3.3 将window传入data中

window传入data中,实现alert弹框。如下代码所示:

<div id="root">
    <h2>今天我们去吃{{info}}--切换次数{{count}}</h2>
    <button @click="change">切换</button>
    <button @click="isHuoguo = !isHuoguo;count++">切换2</button>
    <button @click="window.alert(1)">弹出alert</button>
</div>
<script>
    const vm = new Vue({
        el:'#root',
        data:{
            isHuoguo:true,
            count:0,
            window      //相当于window:window
        },
        computed:{
            info() {
                return this.isHuoguo?'火锅':'南京大排档';
            }
        },
        methods: {
            change() {
                this.count++;
                this.isHuoguo = !this.isHuoguo;
            }
        },
    })
</script>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/840695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

高并发负载均衡---LVS

目录 前言 一&#xff1a;负载均衡概述 二&#xff1a;为啥负载均衡服务器这么快呢&#xff1f; ​编辑 2.1 七层应用程序慢的原因 2.2 四层负载均衡器LVS快的原因 三&#xff1a;LVS负载均衡器的三种模式 3.1 NAT模式 3.1.1 什么是NAT模式 3.1.2 NAT模式实现LVS的缺点…

c++--二叉树应用

1.根据二叉树创建字符串 力扣 给你二叉树的根节点 root &#xff0c;请你采用前序遍历的方式&#xff0c;将二叉树转化为一个由括号和整数组成的字符串&#xff0c;返回构造出的字符串。 空节点使用一对空括号对 "()" 表示&#xff0c;转化后需要省略所有不影响字符…

【react】react中BrowserRouter和HashRouter的区别:

文章目录 1.底层原理不一样:2.path衣现形式不一样3.刷新后对路山state参数的影响4.备注: HashRouter可以用于解决一些路径错误相关的问题 1.底层原理不一样: BrowserRouter使用的是H5的history API&#xff0c;不兼容IE9及以下版不。 HashRouter使用的是URL的哈希值。 2.path衣…

Element-ui中分页器的使用

<template>中写&#xff1a; js中写&#xff1a;

pytorch的CrossEntropyLoss交叉熵损失函数默认reduction是平均值

pytorch中使用nn.CrossEntropyLoss()创建出来的交叉熵损失函数计算损失默认是求平均值的&#xff0c;即多个样本输入后获取的是一个均值标量&#xff0c;而不是样本大小的向量。 net nn.Linear(4, 2) loss nn.CrossEntropyLoss() X torch.rand(10, 4) y torch.ones(10, dt…

认识 MyBatis + MyBatis如何使用 (MyBatis操作数据库)

前言 本篇介绍了什么是MyBatis&#xff0c;MyBatis的前期配置&#xff0c;MyBatis操作数据库的两种方式&#xff1a;.xml文件 / 注释&#xff0c;使用MyBatis的一些注意&#xff0c;如有错误&#xff0c;请在评论区指正&#xff0c;让我们一起交流&#xff0c;共同进步&#x…

AI 一键去水印:教你无限量使用商业图片的技巧

场景再现 刚开始注册账号(啥账号具体不表了&#xff0c;小编不喜欢的那个)&#xff0c;想弄个闪亮&#xff0c;好看&#xff0c;有个性化的 Logo。作为一名非专美工小白人员&#xff0c;网上翻了很久作图工具&#xff0c;要么就是不好用&#xff0c;好用的大部分都收费。最后没…

如何从零开始配置前端环境以及安装必备的软件插件

文章目录 前言一、VSCode&#xff08;Visual Studio Code&#xff09;1.1 VSCode介绍与安装1.2 VSCode 常用插件安装1.3 VSCode代码格式化 二、Node.js2.1 Node的介绍与安装2. yarn的安装 三、Webpcak3.1 Webpcak的介绍与安装 四、Vue CLI4.1 Vue CLI的安装与介绍 五、初始化Vu…

设计模式-迭代器模式在Java中使用示例

场景 为开发一套销售管理系统&#xff0c;在对该系统进行分析和设计时&#xff0c;发现经常需要对系统中的商品数据、客户数据等进行遍历&#xff0c; 为了复用这些遍历代码&#xff0c;开发人员设计了一个抽象的数据集合类AbstractObjectList&#xff0c;而将存储商品和客户…

MaskedTextBox基本用法

作用&#xff1a;是一个文本输入框&#xff0c;可以指定文本的输入规则。 常用属性&#xff1a; 规定输入的格式 输入字符的占位符&#xff0c;获取输入的数据后留意处理 常用事件&#xff1a; 当输入字符不符合规则时发生 后台代码示范&#xff1a; //掩码文本控件输入不满…

快速实现一个div的水平垂直居中

效果 实现 给父盒子宽高和flex&#xff0c;子盒子margin&#xff1a;auto 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-sc…

管理类联考——写作——论说文——实战篇——行文篇——通用性强,解释多种现象的经典理论——谈必要

前言 本节内容涉及“社会分工理论”“资源稀缺性”“瓶颈理论”等理论。这些理论一般用在“利大于弊式结构”中“整体有必要”的部分&#xff0c;也可用于“AB二元类”题目“谈好处”的部分。 需要注意的是&#xff0c;“有好处”一般指有它更好&#xff1b;“有必要”一般指没…

基于人工智能的中医图像分类系统设计与实现

华佗AI 《支持中医,永远传承古老文化》 本存储库包含一个针对中药的人工智能图像分类系统。该项目的目标是通过输入图像准确识别和分类各种中草药和成分。 个人授权许可证 版权所有 2023至2050特此授予任何获得华佗AI应用程序(以下简称“软件”)副本的人免费许可,可根据以…

285 · 高楼大厦

链接&#xff1a;LintCode 炼码 - ChatGPT&#xff01;更高效的学习体验&#xff01; 题解&#xff1a; 1.从左往右维护一个单调递减&#xff0c;栈的长度就是&#xff0c;可以看到最多的高楼 2.从右往后也是维护一个单调递减的栈 class Solution { public:/*** param arr:…

Python中的PDF文本提取:使用fitz和wxPython库(带进度条)

引言&#xff1a; 处理大量PDF文档的文本提取任务可能是一项繁琐的工作。本文将介绍一个使用Python编写的工具&#xff0c;可通过简单的操作一键提取大量PDF文档中的文本内容&#xff0c;极大地提高工作效率。 import wx import pathlib import fitzclass PDFExtractor(wx.Fr…

谷歌、Edge等浏览器截图长图的方法

目录 序 谷歌浏览器 步骤1&#xff1a;打开开发者工具&#xff08;右上角->更多开发工具->开发工具&#xff09;也可以直接按F12 步骤2&#xff1a;按组合键CtrlShiftP&#xff0c;打开浏览器的console功能菜单的指令搜索栏 步骤3&#xff1a;搜索框输入full,找到Cap…

LeetCode--HOT100题(19)

目录 题目描述&#xff1a;54. 螺旋矩阵&#xff08;中等&#xff09;题目接口解题思路代码 PS: 题目描述&#xff1a;54. 螺旋矩阵&#xff08;中等&#xff09; 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 Le…

socker套接字

1.打印错误信息 2.socketaddr_in结构体 结构体&#xff1a; &#xff08;部分库代码&#xff09; (宏中的##) 3.manual TCP: SOCK_STREAM &#xff1a; 提供有序地&#xff0c;可靠的&#xff0c;全双工的&#xff0c;基于连接的流式服务 UDP: 面向数据报

C语言单链表OJ题(较易)

一、移除链表元素 leetcode链接 题目描述&#xff1a; 给你一个链表的头节点 head 和一个整数 val &#xff0c;请你删除链表中所有满足 Node.val val 的节点&#xff0c;并返回 新的头节点 。 思路&#xff1a; 正常遍历&#xff0c;找到value的值与题目中相同的结点去fr…

Statefulset 实战 3

上一部分我们说到如何使用 Statefulset 部署有状态的应用&#xff0c;Statefulset 可以做到部署的 每一个 pod 能够独立的拥有一个持久卷声明和持久卷 之前我们 用 Statefulset 和 ReplicaSet 对比&#xff0c;自然他们是有相似之处和不同之处&#xff0c;不同之处前面的文章已…