美文网首页
vue 中 深度监听数据变化

vue 中 深度监听数据变化

作者: kopsht | 来源:发表于2020-12-01 09:14 被阅读0次

    原文 [https://michaelnthiessen.com/how-to-watch-nested-data-vue/]

    本文解决:

    1. watch 与 computed 应该使用哪个;
    2. watch中绑定object或array时,数据没有更新(deep);
    3. prop的默认值(default)没有触发watch函数(immediate);
    4. 多个prop更新时触发同一个处理函数

    watch 方法是什么

    在Vue中,我们可以[监视属性何时更改]并对响执行一些操作。

    例如,如果colour发生变化,我们console一些文字:

    export default {
      name: 'ColourChange',
      props: ['colour'],
      watch: {
        colour()
          console.log('The colour has changed!');
        }
      }
    }
    

    这些观察者使我们能够做各种有用的事情。

    但是很多时候,我们本来只需要使用computed实际上却使用率watch。

    应该使用watch还是computed?

    watched通常会与computed属性混淆,因为它们的运作方式相似。知道何时使用哪一个更难。

    但是我想出了一个很好的经验法则。

    改变state使用computed,需要副作用使用watch。

    任何异步或发生在component外的,都算是副作用

    常见的例子有:

    • 请求接口获取数据
    • 操作DOM
    • 使用浏览器API,例如local storage 或 audio playback

    这些不会直接影响组件的被认为是副作用

    如果不执行此类操作,需要响应其他变化更新计算时,computed确实非常有用。

    但有时,computed没什么意义。比如渲染<template>的话data就够了。如果需要更新它以响应属性更改,则需要使用观察程序。

    注意:使用watch更新状态时要小心。这意味着您的组件和父组件都在直接或间接地更新相同的状态。This can get very ugly very fast

    观察嵌套数据—数组和对象

    如果已经确定你需要使用watch而不是computed,但是wach 一个数组或一个对象没能按预期工作
    为什么?

    假设有一个数组数组:

    const array = [1, 2, 3, 4];
    // array = [1, 2, 3, 4]
    

    现在,通过push来更新数组:

    array.push(5);
    array.push(6);
    array.push(7);
    // array = [1, 2, 3, 4, 5, 6, 7]
    

    问题是:array变了吗?

    虽然array的内容变了,但是这个array变量的指针指向的内存地址并没有变,所以这个array容器并没有变化。因此,当watch一个数组或对象时,Vue不知道您已经更改了array或object 内部的 内容。您必须告诉Vue在观察更改时希望它需要监控容器的内部。

    您可以通过在watch上将设置deeptrue并写handler 方法来实现它。

    export default {
      name: 'ColourChange',
      props: {
        colours: {
          type: Array,
          required: true,
        },
      },
      watch: {
        colours: {
          // This will let Vue know to look inside the array
          deep: true,
    
          // We have to move our method to a handler field
          handler()
            console.log('The list of colours has changed!');
          }
        }
      }
    }
    

    现在,Vue能够监控容器的内部的内容了。

    immediate

    观察者仅在prop的值更改时才会触发,但我们通常也需要在启动时触发一次。

    假设我们有一个MovieData组件,它根据movieprop设置服务器获取数据的地址:

      name: 'MovieData',
      props: {
        movie: {
          type: String,
          required: true,
        }
      },
      data() {
        return {
          movieData: {},
        }
      },
    
      watch: {
        // Whenever the movie prop changes, fetch new data
        movie(movie) {
          // Fetch data about the movie
          fetch(`/${movie}`).then((data) => {
            this.movieData = data;
          });
        }
      }
    }
    

    每当movie更新时,watcher就会触发,并获取新数据。

    但是这里还有一个问题。当页面加载时,movie会被设置默认值。但是由于prop还没有改变,所以watch没有被触发。这意味着movie更新之前,不会加载数据。

    那么,如何让我们的watch在页面加载后立即触发?

    我们将其设置immediate为true,然后将需要触发的函数放在handler中:

    watch: {
      // Whenever the movie prop changes, fetch new data
      movie: {
        // Will fire as soon as the component is created
        immediate: true,
        handler(movie) {
          // Fetch data about the movie
          fetch(`/${movie}`).then((data) => {
            this.movieData = data;
          });
        }
      }
    }
    

    好的,现在我认为是时候介绍一下handler了。

    handler

    Watchers有三个不同的属性:

    • immediate
    • deep
    • handler

    我们只是看了前两个,第三个也不难。您可能已经在使用它,而没有意识到它。

    在prop变更时将会调用handler方法

    如果如果不需要immediate或者是deep,我们一般写如下的代码:

    watch: {
      movie: {
        handler(movie) {
          // Fetch data about the movie
          fetch(`/${movie}`).then((data) => {
            this.movieData = data;
          });
        }
      }
    }
    

    而是使用它的简写形式:

    watch: {
      movie(movie) {
        // Fetch data about the movie
        fetch(`/${movie}`).then((data) => {
          this.movieData = data;
        });
      }
    }
    

    最酷的是Vue还允许我们使用String来命名处理函数。如果我们想在两个或更多props发生变化时写处理函数,这很有用。

    以我们的movie组件示例为例,假设我们同时基于movieactor两个prop来获取数据:

    watch: {
      // Whenever the movie prop changes, fetch new data
      movie {
        handler: 'fetchData'
      },
      // Whenever the actor changes, we'll call the same method
      actor: {
        handler: 'fetchData',
      }
    },
    
    methods: {
      // Fetch data about the movie
      fetchData() {
        fetch(`/${this.movie}/${this.actor}`).then((data) => {
          this.movieData = data;
        });
      }
    }
    

    相关文章

      网友评论

          本文标题:vue 中 深度监听数据变化

          本文链接:https://www.haomeiwen.com/subject/izorwktx.html