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

yizhihongxing

是的,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日

相关文章

  • vue3引入Element-plus的详细步骤记录

    以下是使用vue3引入Element-plus的详细步骤记录: 第一步:安装Element-plus 在项目中使用npm安装Element-plus: npm install element-plus –save 第二步:引入Element-plus 在main.js中引入Element-plus并注册组件: import { createApp } fr…

    Vue 2023年5月28日
    00
  • vue中使用TypeScript的方法

    下面将为你详细讲解在vue中使用TypeScript的方法。 1. Vue项目初次使用TypeScript 安装TypeScript 首先,需要全局安装TypeScript: npm install -g typescript 安装完成后,我们可以通过以下命令来检查是否安装成功: tsc –version 创建vue项目 创建一个新的vue项目: vue …

    Vue 2023年5月28日
    00
  • Vue前端导出Excel文件的详细实现方案

    实现Vue前端导出Excel文件主要有两种方案:一种是使用JavaScript库,如:SheetJS、ExcelJS,另一种是使用原生JavaScript实现。 使用SheetJS库实现 SheetJS库提供了一系列API,使得我们可以方便地在前端实现Excel导入导出功能。以下是具体步骤: 步骤一:安装SheetJS npm install xlsx 步骤…

    Vue 2023年5月27日
    00
  • 关于Vue源码vm.$watch()内部原理详解

    关于Vue源码vm.$watch()内部原理详解 1. 简介 vm.$watch() 是 Vue.js 内置的一个 API,用于监控 Vue 实例上的数据变化,并作出相应的响应式行为。在使用 Vue 进行开发时,经常会使用 $watch() 进行数据监听操作。 2. 原理 当我们使用 vm.$watch() 时,会创建一个监听器对象(Dep),用于监听指定属…

    Vue 2023年5月28日
    00
  • Vue.js中的组件系统

    Vue.js是一个流行的JavaScript框架,其中一个主要的功能是组件系统。组件允许开发人员将页面分解为多个可重用的部分,从而使开发更高效和组件复用更简单。 下面将详细讲解Vue.js的组件系统,并提供两个示例来帮助您理解。 什么是Vue.js中的组件? 在Vue.js中,组件是构建Web页面的可重用元素。在页面中,每个组件都具有自己的HTML模板、Ja…

    Vue 2023年5月27日
    00
  • 详解如何使用webpack打包Vue工程

    下面我将为您详细讲解如何使用Webpack打包Vue工程: 环境准备 在使用Webpack打包Vue工程前,我们需要先搭建一些必要的环境: 安装Node.js和npm:Webpack依赖于Node.js和npm,需要先安装Node.js,并将npm更新至最新版本; 全局安装Webpack和Webpack-cli:输入命令npm install -g webp…

    Vue 2023年5月28日
    00
  • 详解用webpack2.0构建vue2.0超详细精简版

    下面是详解“用webpack2.0构建vue2.0超详细精简版”的完整攻略。 一、安装依赖 在开始构建项目前,我们需要先安装相关依赖,执行以下命令: npm i webpack webpack-dev-server vue vue-loader vue-template-compiler css-loader style-loader file-loader…

    Vue 2023年5月27日
    00
  • 关于vue中使用three.js报错的解决方法

    下面是关于vue中使用three.js报错的解决方法的完整攻略。 问题描述 在使用vue.js和three.js的过程中,如果在组件中使用three.js,可能会出现报错,报错信息可能会出现如下: TypeError: THREE.BoxGeometry is not a constructor 或者: THREE.WebGLRenderer.render:…

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