【vue.js】文档解读【day 5】 |侦听器

在这里插入图片描述

如果阅读有疑问的话,欢迎评论或私信!!

侦听器

前言

在computed计算属性中,我们知道如果需要计算“衍生值”:通过监听已有的响应式数据,得到一个新的属性。但是在计算属性中,vue不推荐直接修改属性的值,或者使得其他DOM变化,那么如果我们确实需要产生一些使其他DOM变化时,vue为我们提供了watch侦听器。

基本示例

为了页面更加简介,在演示前先将下面案例中会反复使用的getAnswer函数贴在这里:

<script>
methods: {
    async getAnswer() {
      this.loading = true  //禁止input输入框输入新的数据
      this.answer = 'Thinking...'
      try {
        const res = await fetch('https://yesno.wtf/api')
        this.answer = (await res.json()).answer
      } catch (error) {
        this.answer = 'Error! Could not reach the API. ' + error
      } finally {
        this.loading = false  //处理完成后允许input输入新数据
      }
    }
  }
</script>

使用属性值表示watch值

我们使用watch侦听器时,只需要像computed计算属性一样将方法名绑定在DOM上。例如:

<template>
	<p>Ask a yes/no question:
        <input v-model="question" :disabled="loading" />
    </p>
	<p>{{ answer }}</p>
</template>

<script>
export default {
  data() {
    return {
      question: '',  //将question声明为属性值,不声明的话在watch中无法监听
      answer: 'Questions usually contain a question mark. ;-)',
      loading: false  //设置input的disabled属性,初始值可输入
    }
  },
  watch: {
    // 每当 question 改变时,这个函数就会执行
    question(newQuestion, oldQuestion) { //监听question属性的变化
      if (newQuestion.includes('?') && newQuestion!=oldQuestion) { 
          // watch中可以监听newQuestion新值和oldQuestion旧值属性
          
         //当question中输入新的值时,调用getAnswer方法
        this.getAnswer()
      }  
    }
  },
  
}
</script>

在该案例中,是一个很好的根据DOM中值变化时修改其他DOM中的值的案例。

使用路径表示watch值

同时,watch选项支持把watch中的键设置为用.分隔的路径(即对象嵌套中的路径),可以将上方的代码这样写:

<template>
	<p>Ask a yes/no question:
        <input v-model="some.nested.question" :disabled="loading" />
    </p>
	<p>{{ answer }}</p>
</template>

<script>
export default {
  data() {
    return {
     some:{
        nested:{
          question:''}
      },  //将question声明为属性值,不声明的话在watch中无法监听
      answer: 'Questions usually contain a question mark. ;-)',
      loading: false  //设置input的disabled属性,初始值可输入
    }
  },
  watch: {
    // 每当 question 改变时,这个函数就会执行
    'some.nested.question'(newQuestion, oldQuestion) { //监听question属性的变化
      if (newQuestion.includes('?') && newQuestion!=oldQuestion) { 
          // watch中可以监听newQuestion新值和oldQuestion旧值属性
          
         //当question中输入新的值时,调用getAnswer方法
        this.getAnswer()
      }  
    }
  }
}
</script>

深层侦听器

watch 默认是浅层的:被侦听的属性,仅在被赋新值时,才会触发回调函数——而嵌套属性的变化不会触发。如果想侦听所有嵌套的变更,你需要深层侦听器。

拿上述场景举例:如果监听的是nested而不是question,那么如果只是修改quesiotn值是不会触发监听事件,只有修改整个nested值才可以触发。例如:

<template>
	<p>Ask a yes/no question:
        <input v-model="some.nested.question" :disabled="loading" />
        <button @click="some.nested.question = 'b?'">点我</button>
    </p>
	<p>{{ answer }}</p>
</template>

<script>
export default {
  data() {
    return {
     some:{
        nested:{
          question:''}
      },  //将question声明为属性值,不声明的话在watch中无法监听
      answer: 'Questions usually contain a question mark. ;-)',
      loading: false  //设置input的disabled属性,初始值可输入
    }
  },
  watch: {
    // 每当 question 改变时,这个函数就会执行
    'some.nested'(newQuestion, oldQuestion) { //监听question属性的变化
      if (newQuestion.includes('?') && newQuestion!=oldQuestion) { 
          // watch中可以监听newQuestion新值和oldQuestion旧值属性
          
         //当question中输入新的值时,调用getAnswer方法
        this.getAnswer()
      }  
    }
  }
}
</script>

在上面代码中,我们不应该使用newQuestion.includes(‘?’),因为这里newQuestion是一个对象,而不是字符串。但是我们运行会发现并没有报错,也就是根本没有引起侦听。

在未使用deep深层监听器时,我们修改input值不会引起watch的变化。当修改nested整个对象时才会引起侦听事件,修改button按钮:

<button @click="some.nested = 'b?'">点我</button>

修改button之后我们要注意这里会抛出一个异常,这是正常的,因为我们这个代码需要使用includes(‘?’),而newQuestion是一个对象。由此我们也可以确定确实出发了监听事件。

在修改button之后才会引起侦听事件,那么如果想要不修改整个对象引起侦听就要使用deep,例如:

<template>
	<p>Ask a yes/no question:
        <input v-model="some.nested.question" :disabled="loading" />
        <button @click="some.nested.question = 'b?'">点我</button>
    </p>
	<p>{{ answer }}</p>
</template>

<script>
export default {
  data() {
    return {
     some:{
        nested:{
          question:''}
      },  //将question声明为属性值,不声明的话在watch中无法监听
      answer: 'Questions usually contain a question mark. ;-)',
      loading: false  //设置input的disabled属性,初始值可输入
    }
  },
  watch: {
    // 每当 question 改变时,这个函数就会执行
    'some.nested'(newQuestion, oldQuestion) { //监听question属性的变化
      if (newQuestion.question.includes('?')) { 
          // watch中可以监听newQuestion新值和oldQuestion旧值属性
          
         //当question中输入新的值时,调用getAnswer方法
        this.getAnswer()
      }deep:true
    }
  }
}
</script>

在该代码中,可以正常监听some.nested的变化。但是需要注意的是我们这里删除了newQuestion!=oldQuestion,因为官方文档中提到了:

// 注意:在嵌套的变更中,

// 只要没有替换对象本身,

// 那么这里的 newValueoldValue 相同

可以自己尝试添加之后在该代码前进行console进行调试。

即时回调的侦听器

watch 默认是懒执行的:仅当数据源变化时,才会执行回调。但在某些场景中,我们希望在创建侦听器时,立即执行一遍回调。举例来说,我们想请求一些初始数据,然后在相关状态更改时重新请求数据。

例如上面场景下,我们想在代码执行之前先运行a?,那么我们可以使用和deep同样的属性immediate: true:

<script>
watch: {
    // 每当 question 改变时,这个函数就会执行
    "some.nested": {
      handler(newQuestion, oldQuestion) {
      
        if (newQuestion.question.includes("?")) {
          
          this.getAnswer();
        }
      },
      immediate:true
    },
  },
</script>

回调函数的初次执行就发生在 created 钩子之前。Vue 此时已经处理了 datacomputedmethods 选项,所以这些属性在第一次调用时就是可用的。关于生命周期到后面会详细解释。

一次性侦听器

immediatedeep类似的属性还有once,它设置该侦听器的执行次数,例如:

watch: {
    // 每当 question 改变时,这个函数就会执行
    "some.nested": {
      handler(newQuestion, oldQuestion) {
      
        if (newQuestion.question.includes("?")) {
          
          this.getAnswer();
        }
      },
      once: true
    },
  },
</script>

在侦听一次变化之后就不会再侦听后续的变化。

相关推荐

  1. vue 侦听器

    2024-03-15 08:08:06       46 阅读
  2. vue-侦听器

    2024-03-15 08:08:06       27 阅读
  3. vue侦听器

    2024-03-15 08:08:06       61 阅读
  4. Vue3 watch侦听器

    2024-03-15 08:08:06       44 阅读
  5. Vue学习笔记之侦听器

    2024-03-15 08:08:06       67 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-15 08:08:06       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-15 08:08:06       101 阅读
  3. 在Django里面运行非项目文件

    2024-03-15 08:08:06       82 阅读
  4. Python语言-面向对象

    2024-03-15 08:08:06       91 阅读

热门阅读

  1. 从前端到前端框架

    2024-03-15 08:08:06       43 阅读
  2. 前端框架的发展史

    2024-03-15 08:08:06       46 阅读
  3. DataX-数据迁移Oracle到Mysql-ETL工具

    2024-03-15 08:08:06       37 阅读
  4. abap opensql 官方文档 abap 整洁之道

    2024-03-15 08:08:06       36 阅读
  5. C语言如何定义字符数组?

    2024-03-15 08:08:06       33 阅读
  6. C#按下enter键时keydown无响应的问题

    2024-03-15 08:08:06       43 阅读
  7. 如果保障服务器的安全

    2024-03-15 08:08:06       39 阅读
  8. Retrofit

    Retrofit

    2024-03-15 08:08:06      29 阅读
  9. C# EPPlus导出dataset----Excel3样式

    2024-03-15 08:08:06       39 阅读