vuejs / vue

This is the repo for Vue 2. For Vue 3, go to https://github.com/vuejs/core
http://v2.vuejs.org
MIT License
207.47k stars 33.65k forks source link

[API Request] Adding {skip_watch: true} to Vue.set #4849

Closed firstprayer closed 7 years ago

firstprayer commented 7 years ago

This is not a bug report but a feature request - I don't know a better place to put it so here I am.

The request is to make Vue.set(object, key, value) into

Vue.set(object, key, value, [option = {skip_watch: boolean}])

If skip_watch is true, then do not trigger any customized registered watcher function.

The reason why I need this is the following. I'm using Google's Firebase as the backend storage. Right now the code is something like this

var app = new Vue({
  ...
  data: { name: ''},
});

// Listen on any backend change. This could come from another user's edit.
var fbRef = Firebase.database().ref('user/1/name');
fbRef.on('value', function (newVal) {
  app.name = newVal.val();
});

// Watch Vue edit so any modification of this client will be written to backend.
app.$watch('name', function(newVal) {
  fbRef.set(newVal);
});

Now suppose we receives some new data (due to concurrent edit from another user) on the Firebase's callback, the following will happen:

1) We set 'app.name = {value from database}'; 2) The set in 1) trigger the watch function, therefore we'll write the value back to Firebase 3) Since the value we're writing into Firebase is identical as the old value, it stops there, won't trigger the 'value' callback again

Ideally, it should stops at 1) - we should be smart enough to tell this value is the most up-to-date value coming out from the database, and we don't want to write it back again. The easiest way I can think of is to skip the write back defined in the watcher.

I agree this pattern is not neat, therefore I'm also open to any suggestions on how can I modify the design to avoid the additional write and not modify the API.

posva commented 7 years ago

As a side note, it's better to simply update the firebase ref directly instead of watching the original value to push modifications to firebase. That's how it's done in https://github.com/vuejs/vuefire too.

For your use case, you can simply check if the value changed:

app.$watch('name', function(newVal, oldVal) {
  if (newVal !== oldVal) fbRef.set(newVal)
})

It's a more flexible approach about when to skip watching

firstprayer commented 7 years ago

@posva Thanks! I'm try vuefire

awe