I am a newcomer to vue.js, but I have some experience with React from before.
I have read the vue guidelines and I am trying to understand vue through the concepts from React.
I assume that the vue data
is similar to the React state
, since when it updates the app it will render the page again.
So I would like to do something like ... (the code is in React)
this.setState(Object.assign({}, this.state, { key1: 'value1', key2 : 'value2'}))
But as far as I know, in vue:
this.key1 = 'value1';
this.key2 = 'value2';
Is that correct? I guess vue will render twice since it is 2 statements. How could I set multi values at once?
I have already tried ...
// not working
this.$set(Object.assign({}, thisRef.data, { key1: 'value1', key2: 'value2' }))
// not working
this.data = { key1 : 'value1', key2: 'value2' };
In the second one, data has changed - I have printed value with console.log(this)
- , but it does not render again.
FYI, the full code from the vue template is here. Code review and correction will be very welcomed.
<script>
export default {
layout: 'reactQuickly'
, data: function(){
return {
time: null
, init: null
}
}
, methods: {
startTimer: function(time){
clearInterval(this.init);
let thisRef = this;
let interval = setInterval(
function(){
console.log('2: Inside of interval', time)
let timeLeft = thisRef.time - 1;
if(timeLeft <= 0) clearInterval(interval);
thisRef.time = timeLeft;
// thisRef.$set(Object.assign({}, thisRef.data, { time: timeLeft }))
console.log('thisRef', thisRef, this);}
, 1000);
console.log('1: After interval');
// this.data = { time : time, init: interval };
this.time = time;
this.init = interval;
console.log('this.data', this.data);
// this.$set(Object.assign({}, this.data, { time : time, init: interval}));
}
}
}
</script>
============ Edition ===========
react this.state
and vue this.data
is not same, right?
To me, main confusion starts from that point.
In vue
export default {
data : function() {
return {
foo : 'bar'
}
}
}
and
In react
constructor() {
super()
this.state = {
foo : 'bar'
}
}
are completely different concept, right?
Your concern in the question is not necessary. You don't need to worry about set multi values at once
in Vue.
(I learnt what I am going to say from this awesome article => Updating UIs: value comparison VS mutation tracking.)
React and Vue has very different way of tracking when UI should be updated.
React uses Object Immutability. That's why everytime you setState
, you essentially are creating a completely new object and the entire component rerender based on the new object values.
Vue uses getters/setters on the data object for mutation tracking. When you execute this.key1 = 'value1';
, it will go through the setter
of key1
. In the setter, there's a function to notify the watcher
and add this data changes to a queue.
In case you haven’t noticed yet, Vue performs DOM updates asynchronously. Whenever a data change is observed, it will open a queue and buffer all the data changes that happen in the same event loop. If the same watcher is triggered multiple times, it will be pushed into the queue only once. This buffered de-duplication is important in avoiding unnecessary calculations and DOM manipulations. https://v2.vuejs.org/v2/guide/reactivity.html#Async-Update-Queue
Therefore, when you execute this.key1 = 'value1'; this.key2 = 'value2';
, it won't render twice. Vue automatically queues up the data changes and rerender them together later on.
What I meant to say is, your concern in the question is not necessary. You don't need to worry about set multi values at once
in Vue. React and Vue has very different reactivity system. You might wanna read through the links above to get a better understanding.
(Btw, Vue uses getter/setter now but it will use JS proxy in the future. https://github.com/vuejs/roadmap)
With $set method you can add only one property:
this.$set(this.existingObject, 'newProperty', 'value')
If you need to add multiple reactive properties, use assign method:
this.existingObject = Object.assign({}, this.existingObject, {
newProperty1: 'value',
newProperty2: 22
}
This is also useful when you want to change just some properties in object, without touching the rest of properties. So:
this.existingObject = Object.assign({}, this.existingObject, {
existingProperty2: 'newValue',
existingProperty6: 66
}
And if you are using Babel, and I assume you do, for both cases, adding or modifying some props, you can use latest spread feature:
let newOrExistingProps = {
newProperty: 'value',
existingProperty: 66
}
this.existingObject = {...this.existingObject, ...newOrExistingProps}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With