vue中watch监听器的触发时机(watch的坑及解决)

是的,Vue中的watch监听器在开发过程中经常用到,它可以监听指定的数据对象的变化,并在变化时触发相应的回调函数进行处理。但是由于Vue是响应式框架,watch监听器的触发时机会受到一些意外的影响,从而导致一些坑。本文将结合示例说明Vue中watch监听器的使用和坑及解决办法。

监听对象

Vue中可以使用$watch方法监听对象的属性变化,例如下面这个示例:

<template>
  <div>
    <p>age: {{age}}</p>
    <button @click="changeAge">changeAge</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      age: 18,
    }
  },
  methods: {
    changeAge() {
      this.age = 20
    }
  },
  watch: {
    age(newVal, oldVal) {
      console.log(`age changed from ${oldVal} to ${newVal}`)
    }
  }
}
</script>

在上述代码中,我们定义了一个data对象,其中包含一个age属性。然后通过按钮click事件触发了changeAge方法,将age的值修改为20。同时,使用watch监听age的变化,并在值变化时触发相应的回调打印日志。

watch监听器触发时机

虽然watch监听器可以监听到对象的变化,但它的触发时机需要特别注意。需要注意的是,watch监听器的触发时机不仅受到对象自身的变化,还受到对象的引用变化的影响。

例如下面这个示例:

<template>
  <div>
    <p>age: {{age}}</p>
    <p>person.age: {{person.age}}</p>
    <button @click="changeObj">changeObj</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      age: 18,
      person: {
        age: 20,
      }
    }
  },
  methods: {
    changeObj() {
      this.person = { age: 22 }
    }
  },
  watch: {
    age(newVal, oldVal) {
      console.log(`age changed from ${oldVal} to ${newVal}`)
    },
    'person.age'(newVal, oldVal) {
      console.log(`person.age changed from ${oldVal} to ${newVal}`)
    },
    person: {
      handler(newVal, oldVal) {
        console.log(`person changed from ${JSON.stringify(oldVal)} to ${JSON.stringify(newVal)}`)
      },
      deep: true
    }
  }
}
</script>

在这个示例中,我们监听了age、person.age以及person三个变量的变化。并且使用changeObj方法将person重新赋值为{ age: 22 }。

需要注意的是,在Vue中,对象的引用变化也会触发watch监听器。因此,虽然person.age值未变化,但当person的引用变化时,它自身的watch监听器会触发。 同时,我们还使用了深度监听,因此可以观察到,当person的引用变化后,由于其内部属性age的值变化,因此也会触发深度监听器。最终控制台会输出这个结果:

person changed from {"age":20} to {"age":22}
person.age changed from 20 to 22

watch坑及解决办法

众所周知,Vue中对象的响应式变化是通过监听getter/setter实现的,因此watch的监听器是在setter后同步触发的。但是由于JavaScript的异步执行模型,有些情况下watch监听器的变化会发生在Vue内部的setter之前,从而会引起一些坑。

以DOM操作为例,当我们更新完数据之后,会进行DOM渲染操作。如果在DOM渲染完成之后再去修改数据,Vue的setter是没有问题的。但是如果在DOM渲染之前就去修改了数据,则setter是无法进行DOM更新的。此时如果使用watch监听属性变化,并在回调函数中进行DOM操作显然是错误的。

那么如何解决这个问题呢?Vue提供了一个Vue.nextTick()方法,它会在下一个DOM更新周期之后执行回调函数,从而保证了回调函数的执行时机。 因此,在需要在DOM更新后进行操作的情况下,我们可以利用这个方法。

例如下面这个示例:

<template>
  <div>
    <p>age: {{age}}</p>
    <button @click="changeAge">changeAge</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      age: 18,
    }
  },
  methods: {
    changeAge() {
      this.age = 20
      this.$nextTick(() => {
        console.log('DOM updated')
        this.$refs.paragraph.textContent = this.age
      })
    }
  },
  watch: {
    age(newVal, oldVal) {
      console.log(`age changed from ${oldVal} to ${newVal}`)
    }
  }
}
</script>

在这个示例中,我们在changeAge方法中使用Vue.nextTick()方法,并在回调函数中进行DOM操作。即:改变了age的值后的下一次DOM更新周期,修改对应的p元素的textContent,保证了DOM更新和数据变化的同步性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:vue中watch监听器的触发时机(watch的坑及解决) - Python技术站

(0)
上一篇 2023年5月29日
下一篇 2023年5月29日

相关文章

  • Vue 实现穿梭框功能的详细代码

    实现穿梭框功能需要依赖于 Vue.js 框架和一些 UI 组件库,本文以 element-ui 为例,给出一份详细的代码实现攻略。下面是具体步骤: 步骤一:引入 Element UI 首先,在 index.html 中引入 Element UI: <link rel="stylesheet" href="https://u…

    Vue 2023年5月28日
    00
  • Vue-router编程式导航的两种实现代码

    Vue-router 是 Vue.js 官方的路由管理器,它和 Vue.js 的核心深度集成,让构建单页应用变得非常容易。编程式导航是指在代码中手动改变路由的方式。Vue-router 提供了两种编程式导航的方法。 方法一:$router.push // 在组件内部使用 this.$router.push({ path: ‘/example’, query:…

    Vue 2023年5月27日
    00
  • Vue3.x的版本中build后dist文件中出现legacy的js文件问题

    Vue 3.x的版本中build后dist文件中出现legacy的js文件问题,是由于在Vue 3.x的版本中,开发团队加入了 Webpack 5 的新特性—— 模块还原 /esModule,这些变化导致了一些旧版浏览器中无法兼容这些新特性,因此需要生成一个legacy版本的js文件来兼容这些浏览器。 以下是如何解决这个问题的完整攻略: 1.修改 packa…

    Vue 2023年5月28日
    00
  • 前端大文件上传与下载(分片上传)的详细过程

    前端大文件上传和下载一般采用分片上传和下载的方式,确保上传和下载的大文件不会占用过多的带宽和服务器资源。以下是前端大文件上传和下载的详细过程: 前端大文件上传的详细过程 前端将文件分片,每片数据大小和数量根据实际需求决定,一般大小为1MB – 5MB,数量为10 – 100片。可以使用FileReader API将文件读取为二进制流,然后根据分片大小对二进制…

    Vue 2023年5月28日
    00
  • Vue源码makeMap函数深入分析

    OK,让我来详细讲解“Vue源码makeMap函数深入分析”的完整攻略。 标题 Vue源码makeMap函数深入分析 简介 首先,我们需要知道 makeMap 是什么,它是 Vue 源码中常用的一个函数,主要用于生成一个对象,对象中的 key 都是小写的字符串,同时这些 key 都对应着 true 这个固定的值。makeMap 函数是 Vue 源码中非常重要…

    Vue 2023年5月27日
    00
  • Vue 中批量下载文件并打包的示例代码

    要实现Vue中批量下载文件并打包,可以使用webpack和file-saver库。 安装file-saver库 首先需要安装file-saver库,可以使用npm进行安装,命令如下: npm install file-saver –save 创建download.js 创建一个download.js文件,包含一个方法downloadSingle(url, …

    Vue 2023年5月28日
    00
  • Vue中computed计算属性和data数据获取方式

    下面是关于Vue中computed计算属性和data数据获取方式的完整攻略。 1. 什么是computed计算属性 在Vue中,computed计算属性是一种特殊的属性。它的值不是直接提供的,而是通过计算而来的。computed计算属性是基于它所依赖的数据属性的值进行计算。当依赖的数据属性的值发生改变时,计算属性的值会自动刷新。 computed计算属性常用…

    Vue 2023年5月28日
    00
  • VUE写一个简单的表格实例

    下面是使用VUE.js编写一个简单的表格实例的完整攻略: 步骤一:创建VUE.js实例 首先,我们需要在HTML中引入VUE.js的JavaScript文件,然后再创建一个VUE的实例,代码如下: <!DOCTYPE html> <html> <head> <meta charset="utf-8&quot…

    Vue 2023年5月29日
    00
合作推广
合作推广
分享本页
返回顶部