See https://vuejs.org/v2/guide/reactivity.html#How-Changes-Are-Tracked
Vue walk through all Vue instance's data of its properties and convert them to getter/setters using Object.defineProperty.
Getter & Setter works with Watcher to notify change and allow Watcher to collect dependency
Watcher trigger re-render
Vue performs setter/getter conversion during Vue instance initialization. Property must present in "data" at the time.
Root ("data") level property addition / deletion does not work (they should be declared there from the beginning)
Nested property addition:
Vue.set(vm.someObject, 'b', 2) // vm is Vue instance
this.$set(this.someObject, 'b', 2) // this is Vue instance
Object.assign does not work
// instead of `Object.assign(this.someObject, { a: 1, b: 2 })`, which does not work
this.someObject = Object.assign({}, this.someObject, { a: 1, b: 2 }) // create a new object and replace to trigger change
vue CANNOT detect the following changes
NONO: vm.items[index] = newValue // replace array member
DO: Vue.set(vm.items, index, newValue)
DO: vm.items.splice(index, 1, newValue)
NONO: vm.items.length = newLength // shorten only
DO: vm.items.splice(newlength) // shorten only
NONO: vm.brand_new_property = value // property addition
DO: Vue.set(object, key, value)
DO: vm.$set(vm.some_existing_data_object, ‘newKey’, newValue)
NONO: Object.assign(vm.someData, {newProperty1:val1,newProperty2:val2})
DO: vm.someData = Object.assign({}, vm.someData, {new....})