<h3 dir="auto">What problem does this feature solve?</h3>
<p dir="auto">Hi,</p>
<p dir="auto">I'd like to request a new option for the $watch() function: <code class="notranslate">shallow: boolean;</code>. This option would make watch callback function fire only if any of the first level values in an Array (a tuple) or on Object change. This would offer an alternative to the current behaviour of always calling the watch callback when watching a non-primitive variable (as per <a href="https://github.com/vuejs/vue/blob/4f111f9225f938f7a2456d341626dbdfd210ff0c/src/core/observer/watcher.js#L184">the following comment</a>). It would also be a natural expansion of the <code class="notranslate">deep: boolean;</code> option.</p>
<p dir="auto">Moreover, the first level properties of the watched Arrays and Objects would <em>always</em> be compared used strict equality comparison <code class="notranslate">===</code>, regardless of whether they are primitive values or Arrays/Objects. This is so that the same instances of a class would not trigger the watch callback, as nothing has changed (the use case is: observing an immutable value object).</p>
<p dir="auto">Use case 1: Watching a tuple, aka. watching many variables and having a single callback when any of the variables change. With the <code class="notranslate">shallow: true</code> option, it would be a very clean solution to current necessity of having to hash the tuple somehow (the easiest way is to <code class="notranslate">.join(',')</code> the tuple to produce a string, but not all tuples are made of primitive values, so that's not always this easy). Two tuples should evaluate equal, when all indexes of the old tuple are set to the same values in the new tuple, under the same indexes. It'd be a simple for-each loop that short-circuits on the first inequality in the old and the new tuple.</p>
<p dir="auto">Use case 2: Watching all keys in an Object. This is a very common use case and using <code class="notranslate">deep: true</code> for it is very often not ideal (especially, if the values in the watched Object are also Objects). As in use case 1, here the old and the new Objects would evaluate unequal (and therefore trigger the watch callback), when any of the keys in the old Object doesn't strict-equal the same key in the new Object. Also, if keys are missing or there are extra keys in the new Object, this should also be treated as a change and therefore trigger the watch callback. A common context for this use case is when the watched Object is a hashmap behaving as a "form", whose keys are form keys and values are either primitive variables or value objects. Watching such a hashmap with the proposed <code class="notranslate">shallow: true</code> option would be <em>a massive</em> convenience (e.g. to run validation on every change in the form and enable/disable the submit button).</p>
<p dir="auto">In angular 1, this feature is called <a href="https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watchCollection" rel="nofollow">$watchCollection</a>.</p>
<p dir="auto">Thank you.</p>
<h3 dir="auto">What does the proposed API look like?</h3>
<div class="highlight highlight-source-js notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="class Person {
  constructor(name) {
    this.name = name;
  }
}

const vm = new Vue({
  data: {
    dataHashmap: {
      bartender: new Person('Phil'),
      bouncer: new Person('Rob'),
      janitor: new Person('Tom'),
    }
  }
});

vm.$watch(
  'dataHashmap', 
  () =&gt; { console.log(vm.dataHashmap); }, 
  { shallow: true }
);

vm.$watch(
  (vm) =&gt; { return [vm.dataHashmap.bartender, vm.dataHashmap.janitor]; }, 
  () =&gt; { console.log(vm.dataHashmap); }, 
  { shallow: true }
);"><pre class="notranslate"><span class="pl-k">class</span> <span class="pl-v">Person</span> <span class="pl-kos">{</span>
  <span class="pl-en">constructor</span><span class="pl-kos">(</span><span class="pl-s1">name</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-smi">this</span><span class="pl-kos">.</span><span class="pl-c1">name</span> <span class="pl-c1">=</span> <span class="pl-s1">name</span><span class="pl-kos">;</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">const</span> <span class="pl-s1">vm</span> <span class="pl-c1">=</span> <span class="pl-k">new</span> <span class="pl-v">Vue</span><span class="pl-kos">(</span><span class="pl-kos">{</span>
  <span class="pl-c1">data</span>: <span class="pl-kos">{</span>
    <span class="pl-c1">dataHashmap</span>: <span class="pl-kos">{</span>
      <span class="pl-c1">bartender</span>: <span class="pl-k">new</span> <span class="pl-v">Person</span><span class="pl-kos">(</span><span class="pl-s">'Phil'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
      <span class="pl-c1">bouncer</span>: <span class="pl-k">new</span> <span class="pl-v">Person</span><span class="pl-kos">(</span><span class="pl-s">'Rob'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
      <span class="pl-c1">janitor</span>: <span class="pl-k">new</span> <span class="pl-v">Person</span><span class="pl-kos">(</span><span class="pl-s">'Tom'</span><span class="pl-kos">)</span><span class="pl-kos">,</span>
    <span class="pl-kos">}</span>
  <span class="pl-kos">}</span>
<span class="pl-kos">}</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-s1">vm</span><span class="pl-kos">.</span><span class="pl-en">$watch</span><span class="pl-kos">(</span>
  <span class="pl-s">'dataHashmap'</span><span class="pl-kos">,</span> 
  <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span> <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">vm</span><span class="pl-kos">.</span><span class="pl-c1">dataHashmap</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> 
  <span class="pl-kos">{</span> <span class="pl-c1">shallow</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-s1">vm</span><span class="pl-kos">.</span><span class="pl-en">$watch</span><span class="pl-kos">(</span>
  <span class="pl-kos">(</span><span class="pl-s1">vm</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span> <span class="pl-k">return</span> <span class="pl-kos">[</span><span class="pl-s1">vm</span><span class="pl-kos">.</span><span class="pl-c1">dataHashmap</span><span class="pl-kos">.</span><span class="pl-c1">bartender</span><span class="pl-kos">,</span> <span class="pl-s1">vm</span><span class="pl-kos">.</span><span class="pl-c1">dataHashmap</span><span class="pl-kos">.</span><span class="pl-c1">janitor</span><span class="pl-kos">]</span><span class="pl-kos">;</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> 
  <span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-c1">=&gt;</span> <span class="pl-kos">{</span> <span class="pl-smi">console</span><span class="pl-kos">.</span><span class="pl-en">log</span><span class="pl-kos">(</span><span class="pl-s1">vm</span><span class="pl-kos">.</span><span class="pl-c1">dataHashmap</span><span class="pl-kos">)</span><span class="pl-kos">;</span> <span class="pl-kos">}</span><span class="pl-kos">,</span> 
  <span class="pl-kos">{</span> <span class="pl-c1">shallow</span>: <span class="pl-c1">true</span> <span class="pl-kos">}</span>
<span class="pl-kos">)</span><span class="pl-kos">;</span></pre></div>
<h3 dir="auto">Vue.js version</h3>
<p dir="auto">1.0.21</p>
<h3 dir="auto">Reproduction Link</h3>
<p dir="auto"><a href="http://www.webpackbin.com/412B9bgJb" rel="nofollow">http://www.webpackbin.com/412B9bgJb</a></p>
<h3 dir="auto">Steps to reproduce</h3>
<p dir="auto">click Toggle button</p>
<h3 dir="auto">What is Expected?</h3>
<p dir="auto">when MyComponent is showing, the msg should be hidden</p>
<h3 dir="auto">What is actually happening?</h3>
<p dir="auto">the msg always shows</p>