您当前的位置:首页 > 电脑百科 > 程序开发 > 前端

Vue3 学习笔记,如何使用 Watch 监听数据变化

时间:2023-12-14 13:39:53  来源:今日头条  作者:前端达人

大家好,本篇文章我们继续学习和 Vue 相关的内容,今天我们归纳总结下如何使用 watch 监听组件中的数据变化,以及 computed 和 watch 的区别。

什么是 watch,以及如何使用?

watch 是 Vue.js 中用于监听数据变化的一种机制。它允许我们在数据发生变化时执行特定的操作。

在 Vue 中使用 watch 的方法如下:

1.在 Vue 组件中,定义一个 watch 对象,其中包含要监听的数据属性以及对应的回调函数。

watch: {
  dataName: function(newValue, oldValue) {
    // code
  }
}

其中,dataName 是要监听的数据名称,newValue 是新的值,oldValue 是旧的值。

2.在 Vue 实例中,使用 $watch() 方法进行监听

vm.$watch('someData', function(newVal, oldVal) {
  // do something with newVal
});

注意:watch 回调函数会在侦听的数据发生变化时立即执行,而 computed 属性只有在其依赖的数据发生变化时才会计算。

watch 通常用于监听一个数据的变化并执行复杂的业务逻辑,例如在某个数据变化后需要进行 HTTP 请求或者调用其他函数。

下面是一个简单的 watch 的例子:

<template>
  <div>
    <input v-model="message" type="text" placeholder="请输入内容">
    <p>{{ message }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      message: '',
    }
  },
  watch: {
    message: function (newVal, oldVal) {
      console.log('message changed from ' + oldVal + ' to ' + newVal)
    }
  },
}
</script>

在这个例子中,我们使用了 watch 来监听 message 的变化,并在数据变化时打印出更改前后的值。

当然,watch 还可以接收一个对象,其中可以定义多个监听器。这里有一个例子,它监听了多个数据:

watch: {
  firstName: function (newVal, oldVal) {
    console.log('firstName changed from ' + oldVal + ' to ' + newVal)
  },
  lastName: function (newVal, oldVal) {
    console.log('lastName changed from ' + oldVal + ' to ' + newVal)
  }
}

一些高级用法介绍

1、深度观察 (deep: true):如果你希望对对象内部属性的变化进行监听,可以使用 deep: true 选项。

data() {
  user: {
    name: 'John',
    age: 25
  }
},
watch: {
  'user.name': function (val) {
    console.log('user name changed:', val)
  }
}

在这个例子中,我们监听了 user 对象中的 name 属性,当该属性变化时,会执行回调函数。

2、设置初始值 (immediate: true):如果你希望 watch 在组件创建时立即执行一次,可以使用 immediate: true 选项。

data() {
    count: 0
},
watch: {
    count: {
        handler: function (val, oldVal) {
            console.log('count changed');
        },
        immediate: true
    }
}

3、异步处理 (handler):watch 的回调函数是异步执行的,这意味着如果有多个值在短时间内发生变化,回调函数只会在这些变化结束后执行一次。

watch: {
  searchText: function (val) {
    this.searching = true
    setTimeout(() => {
      this.searchData(val)
      this.searching = false
    }, 500)
  }
}

在这个例子中,我们监听了 searchText 属性,并在数据变化后延迟 500 毫秒执行搜索操作。

4、使用 watch 观察器实现自动保存

data() {
  content: ''
},
watch: {
  content: function (val) {
    localStorage.setItem('content', val)
  }
}

在这个例子中,我们监听了 content 属性,并在数据变化时自动保存到本地存储中。

应用场景介绍

watch 监听器还有许多其他的应用场景,例如:

  • 在表单输入时进行验证,并显示错误消息
  • 在表格中进行排序和过滤
  • 在地图上实时显示用户位置
  • 监听路由变化并执行相应操作
  • 监听窗口大小变化并调整布局
  • 监听滚动事件并实现懒加载
  • ……

1.在表单输入时进行验证,并显示错误消息

<template>
  <form>
    <label>
      EmAIl:
      <input v-model="email" @keyup="validateEmail"/>
    </label>
    <p v-if="error">{{ error }}</p>
  </form>
</template>

<script>
export default {
  data() {
    return {
      email: '',
      error: ''
    }
  },
  watch: {
    email: {
      immediate: true,
      handler(val) {
        if (!val.includes('@')) {
          this.error = 'Invalid email address'
        } else {
          this.error = ''
        }
      }
    }
  }
}
</script>

2.在地图上实时显示用户位置

<template>
  <div>
    <div id="map"></div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      userLocation: {
        lat: 0,
        lng: 0
      },
      map: null
    }
  },
  mounted() {
    this.map = new google.maps.Map(document.getElementById("map"), {
      center: { lat: 0, lng: 0 },
      zoom: 8
    });
    navigator.geolocation.getCurrentPosition(position => {
      this.userLocation = {
        lat: position.coords.latitude,
        lng: position.coords.longitude
      }
    });
  },
  watch: {
    userLocation: {
      deep: true,
      handler(val) {
        this.map.setCenter(val);
        new google.maps.Marker({
          position: val,
          map: this.map
        });
      }
    }
  }
}
</script>

在这个示例中,我们使用了 watch 来监听 userLocation 的变化,在用户位置发生变化时,使用 setCenter 方法将地图中心设置为用户当前位置,并使用 google maps API 在地图上添加一个标记,显示用户当前位置。

注意:这个例子需要引入 google maps 的 js 文件。

3、监听路由变化并执行相应操作

<template>
  <!-- 省略 -->
</template>

<script>
export default {
  watch: {
    $route(to, from) {
      // 根据路由变化执行相应操作
      if (to.path === '/home') {
        this.getHomeData()
      } else if (to.path === '/about') {
        this.getAboutData()
      }
    }
  },
  methods: {
    getHomeData() {
      // 获取首页数据
    },
    getAboutData() {
      // 获取关于页数据
    }
  }
}
</script>

4、监听窗口大小变化并调整布局

<template>
  <!-- 省略 -->
</template>

<script>
export default {
  data() {
    return {
      windowWidth: 0
    }
  },
  created() {
    this.windowWidth = window.innerWidth
  },
  watch: {
    windowWidth(newWidth, oldWidth) {
      // 监听窗口大小变化并调整布局
      if (newWidth < 768) {
        // 小屏幕布局
      } else {
        // 大屏幕布局
      }
    }
  },
  mounted() {
    window.addEventListener('resize', () => {
      this.windowWidth = window.innerWidth
    })
  }
}
</script>

5、监听滚动事件并实现懒加载

<template>
  <div class="container" ref="container" @scroll="handleScroll">
    <img v-for="(item, index) in images" :key="index" :src="item.src" v-show="item.isLoaded" />
  </div>
</template>

<script>
export default {
  data() {
    return {
      images: [
        { src: 'image1.jpg', isLoaded: false },
        { src: 'image2.jpg', isLoaded: false },
        { src: 'image3.jpg', isLoaded: false },
        // ...
      ]
    }
  },
  mounted() {
    // 初始化加载第一屏图片
    this.lazyLoad();
  },
  methods: {
    handleScroll() {
      this.lazyLoad();
    },
    lazyLoad() {
      const container = this.$refs.container;
      const imageList = Array.from(container.querySelectorAll('img'));
      // 遍历图片列表,如果图片进入了可视区域,就加载
      imageList.forEach(img => {
        if (this.isInViewport(img)) {
          img.src = img.dataset.src;
          img.isLoaded = true;
        }
      });
    },
    isInViewport(img) {
      // 获取图片相对于视口的位置
      const rect = img.getBoundingClientRect();
      // 判断图片是否进入了可视区域
      return rect.top < window.innerHeight && rect.bottom > 0;
    }
  },
  watch: {
    images: {
      handler: function(newVal, oldVal) {
        // 每当图片加载完成时,就移除已加载图片的 isLoaded 属性
        newVal.forEach((item, index) => {
          if (item.isLoaded) {
            this.$set(this.images[index], 'isLoaded', false);
          }
        });
      },
      deep: true
    }
  }
}
</script>

注意:需要注意的是,在这个案例中,因为images数组中的对象被改变了,所以需要设置deep: true来监听对象

总之,watch 是一个非常强大和灵活的功能,它可以在数据变化时执行任何操作,并且可以与 computed 计算属性配合使用,来实现更复杂的逻辑。

computed 和 watch 的区别

watch和computed都可以监听Vue实例中的数据变化,但是它们有着明显的不同。

watch

computed

用于监听某个特定的数据变化。

用于计算属性,可以计算出一个新的值。

每次数据变化都会触发回调函数。

仅在相关依赖发生改变时才会触发重新计算。

适用于异步操作或复杂逻辑。

适用于简单计算。

不可以在html模板中使用

可以在HTML模板中使用

没有返回值

有返回值/getter

可以修改data中的数据

也可以使用setters 修改 data 中的数据

总之,如果你需要在数据变化时执行异步操作或复杂逻辑,使用watch是更好的选择;如果你需要在数据变化时计算出一个新值,使用computed是更好的选择。

关于watch的性能

watch的性能取决于你的代码实现方式和监听的数据量。

  • 监听的数据量:如果你监听了大量的数据,那么 watch 的性能可能会受到影响。
  • 代码实现:如果你在 watch 回调函数中执行了复杂的逻辑或异步操作,那么 watch 的性能可能会受到影响。
  • 如果你只是需要在数据变化时执行一些简单的操作,那么 watch 的性能应该是可以接受的。

所以,在使用watch时,应该注意监听的数据量,并且在watch回调函数中尽量少执行复杂的逻辑.总之,watch监听数据更新并执行回调函数,性能会受到监听数据量和回调函数实现方式的影响,如果有性能问题,应该优化监听的数据量和回调函数的实现方式.

结束

今天的文章就介绍到这里,关于 watch 的用法你学会了,希望今天的文章能帮助到你,感谢你的阅读。如果你喜欢我的分享,别忘了点赞转发,让更多的人看到,最后别忘记点个关注,你的支持将是我分享最大的动力,后续我会持续输出更多内容,敬请期待。



Tags:Vue3   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
SpringBoot3+Vue3 开发高并发秒杀抢购系统
开发高并发秒杀抢购系统:使用SpringBoot3+Vue3的实践之旅随着互联网技术的发展,电商行业对秒杀抢购系统的需求越来越高。为了满足这种高并发、高流量的场景,我们决定使用Spring...【详细内容】
2024-01-14  Search: Vue3  点击:(90)  评论:(0)  加入收藏
vue3中 ref和 reactive的区别 ?
最近有朋友在面试过程中经常被问到这么一个问题,vue3 中的ref 和 reactive的区别在哪里,为什么 要定义两个API 一个 api不能实现 响应式更新吗??带着这个疑问 ,我们 接下来进行逐...【详细内容】
2024-01-03  Search: Vue3  点击:(36)  评论:(0)  加入收藏
React18 与 Vue3 全方面对比
1. 编程风格 & 视图风格1.1 编程风格 React 语法少、难度大;Vue 语法多,难度小例如指令:Vue<input v-model="username"/><ul> <li v-for="(item,index) in list" :key="inde...【详细内容】
2024-01-03  Search: Vue3  点击:(72)  评论:(0)  加入收藏
Vue3 学习笔记,如何使用 Watch 监听数据变化
大家好,本篇文章我们继续学习和 Vue 相关的内容,今天我们归纳总结下如何使用 watch 监听组件中的数据变化,以及 computed 和 watch 的区别。什么是 watch,以及如何使用?watch 是...【详细内容】
2023-12-14  Search: Vue3  点击:(163)  评论:(0)  加入收藏
Vue3 学习笔记,如何理解 Computed 计算属性
大家好,本篇文章我们继续学习和 Vue 相关的内容,今天我们归纳总结下什么是 computed 计算属性、如何使用和应用场景,以及 computed 和 Method 事件的区别和应用场景。什么是 co...【详细内容】
2023-12-11  Search: Vue3  点击:(199)  评论:(0)  加入收藏
Vue3 学习笔记,如何定义事件以及如何理解响应式
如何定义事件在 Vue 中,可以使用 v-on 指令来绑定事件监听器。下面是一个示例,在点击按钮时触发事件处理程序:<template> <div> <button v-on:click="incrementCounter">{{...【详细内容】
2023-12-06  Search: Vue3  点击:(136)  评论:(0)  加入收藏
最全Vue3开源管理系统汇总
搭建一个后台管理,从零开始开发,其实并不容易,在众多开源管理后台中,Vue3是一个备受瞩目的选择。它是一个现代化的前端框架,具有高效、灵活、易用等特点,今天,要为大家介绍几款开源...【详细内容】
2023-11-24  Search: Vue3  点击:(202)  评论:(0)  加入收藏
Vue3问题:如何实现El-table内容超出省略提示?第三条很少有人会
一、需求分析,问题描述1、需求一个表格,分表头、表体、表尾三部分。当每个单元格的内容过长超出时,需要省略,用省略号代替超出的部分。同时,当鼠标移入上去时,会在上方弹出一个小...【详细内容】
2023-11-23  Search: Vue3  点击:(90)  评论:(0)  加入收藏
Spring Boot + Vue3 前后端分离 实战wiki知识库系统
下栽の地止:https://www.itwangzi.cn/2508.html Spring Boot + Vue3 前后端分离 实战wiki知识库系统在当今的Web应用开发中,前后端分离已经成为了一种主流的开发模式。Spring...【详细内容】
2023-11-18  Search: Vue3  点击:(142)  评论:(0)  加入收藏
深入详解Vue3中的Mock数据模拟
Vue3 前端开发时,需要api请求模拟和数据模拟,我将在接下来的时间写Mock模拟和json-server模拟。两种比较流行的模式,现在先介绍mock模式。使用NPM安装Mock.js库Mock.js是一个轻...【详细内容】
2023-11-07  Search: Vue3  点击:(158)  评论:(0)  加入收藏
▌简易百科推荐
20k级别前端是怎么使用LocalStorage的,想知道吗?
当咱们把咱们想缓存的东西,存在localStorage、sessionStorage中,在开发过程中,确实有利于咱们的开发,咱们想看的时候也是一目了然,点击Application就可以看到。前言大家好,我是林...【详细内容】
2024-03-26  前端之神  微信公众号  Tags:前端   点击:(10)  评论:(0)  加入收藏
前端不存在了?盲测64%的人更喜欢GPT-4V的设计,杨笛一等团队新作
3 月 9 日央视的一档节目上,百度创始人、董事长兼 CEO 李彦宏指出,以后不会存在「程序员」这种职业了,因为只要会说话,人人都会具备程序员的能力。「未来的编程语言只会剩下两种...【详细内容】
2024-03-11  机器之心Pro    Tags:前端   点击:(9)  评论:(0)  加入收藏
前端开始“锈化”?Vue团队开源JS打包工具:基于Rust、速度极快、尤雨溪主导
Vue 团队已正式开源Rolldown &mdash;&mdash; 基于 Rust 的 JavaScrip 打包工具。Rolldown 是使用 Rust 开发的 Rollup 替代品,它提供与 Rollup 兼容的应用程序接口和插件接口...【详细内容】
2024-03-09  OSC开源社区    Tags:Vue   点击:(11)  评论:(0)  加入收藏
两年前端经验还不会手写Promise?
什么是promise?当我们处理异步操作时,我们经常需要进行一系列的操作,如请求数据、处理数据、渲染UI等。在过去,这些操作通常通过回调函数来处理,但是回调函数嵌套过多会导致代码...【详细内容】
2024-03-07  海燕技术栈  微信公众号  Tags:Promise   点击:(23)  评论:(0)  加入收藏
网站开发中的前端和后端开发有什么区别
前端开发和后端开发都是干什么的?有哪些区别?通俗地讲,前端干的工作是用户可以直接看得见的,而后端开发的工作主要在服务端,用户不太能直接看到。虽然前端开发和后端开发的工作有...【详细内容】
2024-02-21  CarryData    Tags:前端   点击:(31)  评论:(0)  加入收藏
网站程序开发中的前后端分离技术
随着互联网的快速发展和技术的不断创新,传统的网站开发模式已经难以满足日益增长的业务需求。为了提高开发效率、增强系统的可维护性和可扩展性,前后端分离技术逐渐成为了网站...【详细内容】
2024-01-31  网站建设派迪星航    Tags:前后端分离   点击:(23)  评论:(0)  加入收藏
如何优雅的实现前端国际化?
JavaScript 中每个常见问题都有许多成熟的解决方案。当然,国际化 (i18n) 也不例外,有很多成熟的 JavaScript i18n 库可供选择,下面就来分享一些热门的前端国际化库!i18nexti18ne...【详细内容】
2024-01-17  前端充电宝  微信公众号  Tags:前端   点击:(67)  评论:(0)  加入收藏
Vue中Scope是怎么做样式隔离的?
scope样式隔离在 Vue 中,样式隔离是通过 scoped 特性实现的。当在一个组件的 <style> 标签上添加 scoped 特性时,Vue 会自动为这个样式块中的所有选择器添加一个唯一的属性,以...【详细内容】
2024-01-04  海燕技术栈  微信公众号  Tags:Vue   点击:(80)  评论:(0)  加入收藏
vue3中 ref和 reactive的区别 ?
最近有朋友在面试过程中经常被问到这么一个问题,vue3 中的ref 和 reactive的区别在哪里,为什么 要定义两个API 一个 api不能实现 响应式更新吗??带着这个疑问 ,我们 接下来进行逐...【详细内容】
2024-01-03  互联网高级架构师  今日头条  Tags:vue3   点击:(36)  评论:(0)  加入收藏
React18 与 Vue3 全方面对比
1. 编程风格 & 视图风格1.1 编程风格 React 语法少、难度大;Vue 语法多,难度小例如指令:Vue<input v-model="username"/><ul> <li v-for="(item,index) in list" :key="inde...【详细内容】
2024-01-03  爱做梦的程序员  今日头条  Tags:Vue3   点击:(72)  评论:(0)  加入收藏
站内最新
站内热门
站内头条