TL; DR
- When you add a new attribute to data
vm.$set(vm.info,'newKey','newValue')
- When data is an array,
- When you set an array item directly using an index, for example:
vm.items[indexOfItem] = newValue
usevm.items.splice(indexOfItem, 1, newValue)
- When you modify the length of an array, for example:
vm.items.length = newLength
usevm.items.splice(newLength)
- When you set an array item directly using an index, for example:
Installation and initial use of vUE
Vue is a progressive framework for building user interfaces. So-called progressive: Vue + Components + vue-router + vuex + VUe-CLI can select corresponding functions as required.
Mkdir vue-apply; cd vue-apply; npm init -y; NPM I vue.
Take a look at the HTML file shown below, click on the browser, and the browser console vm. MSG =0
<div id="app">{{msg}}</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:'#app'.// Template replaces the #app tag
// template:'<h1>en</h1>',
data:{msg:'msg'}
})
vm.msg = 'msg'
</script>
Copy the code
Tell me about MVVM MVC
MVC is actually a model view model. Traditionally, all the logic is in the controller, which is difficult to maintain. User input => controller => Data changes. If the data changes, you need to obtain the DOM, manipulate the properties, and then render the data to the view. MVVM is actually a Model View viewModel data change driven view. The data changes, so you don’t have to take the DOM and change the content of the DOM. The data changes on this side, the VM listens, and the view changes automatically. The most obvious one is that you don’t need document.querySelector or anything like that anymore.
The essence of the vm
The VM is responsible for changing the data, and the view can change automatically. The principle behind all this magic is Object.defineProperty. It’s basically reading properties and setting properties that are being listened for, and when that happens, doing something. Let’s play a demo.
// Read the properties above obj and set the listener
let obj = {
name:'huahua'.age:18
}
function observer(obj){
if(typeof obj === 'object') {for (const key in obj) {
defineReactive(obj,key,obj[key])
}
}
}
// The return value of get is the value that you finally read. So the value is set for reading.
Obj. Name = newVal; obj. Name = newVal;
function defineReactive(obj,key,value){
Object.defineProperty(obj,key,{
get:function(){
console.log('You're reading.')
// if happy, value++ is used, so you can see that the value read is always one more than the set value, because return is the value read
return value
},
set:function(newVal){
console.log('Data updated')
value = newVal
}
})
}
observer(obj)
obj.age = 2
console.log(obj.age)
Copy the code
When the browser is executing, the console can also perform operations similar to obj.name=”hua1″. Obj. name={firstName :’hua’, lastName :’piaoliang’}; Obj.name.lastname =’o’ so you can’t listen for property changes. Because the new assignment object is not listening for its properties. So the function needs to be improved. You need to add observer(value) to the first line of defineReactive. If the value is an object, the object data needs to be hijacked. Similarly, we need to add this row to set.
function defineReactive(obj,key,value){
// Note here !!!!!!!
observer(value)
Object.defineProperty(obj,key,{
get:function(){
return value
},
set:function(newVal){
// Note here !!!!!!!
observer(newVal)
console.log('Data updated')
value = newVal
}
})
}
Copy the code
If obj.name=[1,2,3]; Push (4) finds no notification again because Object.defineProperty does not support listening for array changes. So we need to override the method on the array. It is theoretically possible to listen on arrays, but the performance cost is not proportional to the benefit, so VUE is not implemented.
// Rewrites most of the methods on the array. But if you [1,2].length--, this can't be captured
let arr = ['push'.'slice'.'split']
arr.forEach(method= >{
let oldPush = Array.property[method]
Array.property[method] = function(value){
console.log('Data Update')
oldPush.call(this,value)
}
})
Copy the code
Note the pit when using vUE
As explained above, the underlying logic of VUe2.0 is probably this logic, so use the points to note:
-
Because the data was hijacked in the first place. So there is no data hijacking later if you bind a new property. If you need to call vm.$set(vm.info,’newKey’,’newValue’), vm is an instance of vue.
-
When the property value is an array, when the array changes, it doesn’t track the change. Because arrays are objects, object.defineProperty does not support arrays, so Vue overwrites all of the array’s methods to invoke the change event when the array method is called. But you can’t control arrays by attributes or indexes, like length and index.
-
Summary: On data, bind all attributes to avoid adding new attributes later. If it is an array, you can only modify the array using array methods. As an example, console vm.arr– finds that the view does not change, vm.arr.push(4) does
<div id="app">{{msg}}{{arr}}</div>
<script src="node_modules/vue/dist/vue.js"></script>
<script>
let vm = new Vue({
el:'#app'.// Template replaces the #app tag
// template:'<h1>en</h1>',
data:{msg:'msg'.arr: [1.2.3]}
})
vm.msg = 'msg'
</script>
Copy the code