VueJS - 跳过观察者的第一个变化

VueJS - Skip watcher's first change

我正在为我正在制作的应用程序在 VueJS 中创建一个组件,它有一些观察者在我的 var 更改时将逻辑应用于组件的其他部分。一旦组件被初始化,在用户通过 Axios 完成一些事件后,它仍然需要通过来自服务器的一些数据来设置。此数据从主应用程序发出的事件获取到组件。现在问题是这个 var 通常会改变(并非总是如此),但我不希望第一次应用该逻辑,所以我决定设置一个标志并在观察者中将其检查为 return ,但是它没有发生:一旦我将该标志设置回 true(它检查 !this.flag),无论如何都会触发观察者。这是代码:

data(){
    return {
        isSet: false,
        myVar: {
            first: 0,
            second: 0
        }
    }
},
watch: {
    'myVar.first': {
        handler: function(newVal, oldVal){
            if(!this.isSet || other.condition){return}
            console.log('first triggered');
        },
        immediate: false
    },
    'myVar.second': {
        handler: function(newVal, oldVal){
            if(!this.isSet || other.condition){return}
                console.log('second triggered');
        },
        immediate: false
    }
},
methods: {
    setBus(){ // gets called on created(){}
        let self = this;
        Bus.$on('my-event', function(c){
            self.doFirstSet(c);
        });
    },
    doFirstSet(c){
        // do other setting
        if(c.someCondition){
            this.doExtraConfig(c);
        }
        this.isSet = true; // at this point is when the watchers get triggered
    },
    doExtraConfig(c){
        // do more stuff
        if('first' in c){
            this.myVar.first = c.first;
        }else if('second' in c){
            this.myVar.second = c.second;
        }
        console.log("watchers don't get triggered yet");
    }
}

知道如何在旗帜改变时阻止他们开火吗?

您应该简单地声明一个布尔变量,它定义您的数据获取是否完成。 默认情况下,您将其设置为 false doneFetching: false,一旦您完成获取逻辑,您将调用 this.doneFetching = true.

在那之后,您在观察者中所要做的就是一个干净而简单的 if(this.doneFetching){...} 这个简单的逻辑应该可以防止您的观察者逻辑在您需要之前被触发。

您可以使用实例的 $watch() 方法在组件中的任何位置开始观察数据元素。这样,观察者就不会在 Vue 实例的实例化中被实例化,正如 Docs 指定的那样:

"The Vue instance will call $watch() for each entry in the [watch] object at instantiation."

所以,您可能正在寻找这个:

data: {
  return() {
    data: null,
  };
},

mounted() {
  api.fetchList().then((response) => {
    this.data = response.dataFetched
    this.$watch('data', this.dataWatcher);
  });
},

methods: {
  dataWatcher() {
    // Code won't execute after this.data assignment at the api promise resolution
  },
}

在这种简单的情况下,Badgy 的响应更为直接,尽管您可以避免使用 doneFetching 变量。如果我需要更多控制,我会使用 $watch():它实际上是 returns 一个 "unwatch" 函数,您可以调用它来删除它 (Check it out)。

还请记住,观察者应该用于边缘情况,并避免在其他观察者内部改变观察变量。如果不小心使用,这可能会损害数据和方法之间的 Vue 反应性 "orthogonality"。

Badgy 的响应似乎不那么具有侵扰性,也不太容易出错。

我们项目中使用的经过实践检验的方法,尤其是跟踪更改,如下所示:

export default {
  data: () => {
    dataLoaded: false,
    valueThatChanges: 'defaultValue',
  },
  mounted () {
    let self = this
    loadData().then((result) => {
      self.valueThatChanges = result
      self.$nextTick(() => { //with this we skip the first change
        self.dataLoaded = true
      })
    })
  },
  methods: {
    loadData() {
      //your implementation
      return result
    }
  },
  watch: {
    valueThatChanges: function(newValue, oldValue) {
      if (this.dataLoaded) {
        //send tracking change
        console.log('Value was changed from ' + oldValue + ' to ' + newValue + ' via interaction, not by loading')
      }
    }
  }
}