简体   繁体   English

vue.js:如何用对象更新状态?

[英]vue.js: how to update state with object?

I am a newcomer to vue.js, but I have some experience with React from before.我是 vue.js 的新手,但我之前对 React 有一些经验。

I have read the vue guidelines and I am trying to understand vue through the concepts from React.我已经阅读了 vue 指南,并试图通过 React 的概念来理解 vue。

I assume that the vue data is similar to the React state , since when it updates the app it will render the page again.我假设 vue data类似于 React state ,因为当它更新应用程序时,它会再次呈现页面。

So I would like to do something like ... (the code is in React)所以我想做类似......(代码在 React 中)

this.setState(Object.assign({}, this.state, { key1: 'value1', key2 : 'value2'}))

But as far as I know, in vue:但据我所知,在vue中:

this.key1 = 'value1';
this.key2 = 'value2';

Is that correct?那是对的吗? I guess vue will render twice since it is 2 statements.我猜 vue 会渲染两次,因为它是 2 个语句。 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.在第二个中,数据发生了变化 - 我用console.log(this) - 打印了值,但它不会再次呈现。

FYI, the full code from the vue template is here.仅供参考,vue 模板的完整代码在这里。 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? react this.state和 vue this.data不一样吧? 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.您无需担心在 Vue set multi values at once

(I learnt what I am going to say from this awesome article => Updating UIs: value comparison VS mutation tracking .) (我从这篇很棒的文章中学到了我要说的内容 => 更新 UI:值比较 VS 突变跟踪。)

React and Vue has very different way of tracking when UI should be updated. React 和 Vue 有非常不同的方式来跟踪 UI 何时应该更新。

React uses Object Immutability. React 使用对象不变性。 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.这就是为什么每次你setState时,你实际上是在创建一个全新的对象,并且整个组件基于新的对象值重新呈现。

Vue uses getters/setters on the data object for mutation tracking. Vue 在数据对象上使用 getter/setter 进行突变跟踪。 When you execute this.key1 = 'value1';当你执行this.key1 = 'value1'; , it will go through the setter of key1 . ,它将通过key1setter In the setter, there's a function to notify the watcher and add this data changes to a queue.在 setter 中,有一个功能可以通知watcher并将此数据更改添加到队列中。

In case you haven't noticed yet, Vue performs DOM updates asynchronously.如果您还没有注意到,Vue 会异步执行 DOM 更新。 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.如果同一个 watcher 被多次触发,它只会被推入队列一次。 This buffered de-duplication is important in avoiding unnecessary calculations and DOM manipulations.这种缓冲的重复数据删除对于避免不必要的计算和 DOM 操作很重要。 https://v2.vuejs.org/v2/guide/reactivity.html#Async-Update-Queue https://v2.vuejs.org/v2/guide/reactivity.html#Async-Update-Queue

Therefore, when you execute this.key1 = 'value1'; this.key2 = 'value2';因此,当你执行this.key1 = 'value1'; this.key2 = 'value2'; this.key1 = 'value1'; this.key2 = 'value2'; , it won't render twice. 它不会渲染两次。 Vue automatically queues up the data changes and rerender them together later on. Vue 会自动将数据更改排队并稍后将它们重新渲染在一起。

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.您无需担心在 Vue set multi values at once React and Vue has very different reactivity system. React 和 Vue 有非常不同的反应系统。 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 ) (顺便说一句,Vue 现在使用 getter/setter,但将来会使用 JS 代理。https://github.com/vuejs/roadmap

With $set method you can add only one property:使用 $set 方法,您只能添加一个属性:

this.$set(this.existingObject, 'newProperty', 'value')

If you need to add multiple reactive properties, use assign method:如果您需要添加多个反应属性,请使用 assign 方法:

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:如果你使用 Babel,我假设你在这两种情况下都这样做,添加或修改一些道具,你可以使用最新的传播功能:

let newOrExistingProps = {
  newProperty: 'value',
  existingProperty: 66
}

this.existingObject = {...this.existingObject, ...newOrExistingProps}

Vuex Store: store.js Vuex 商店:store.js

 export default new Vuex.Store({
  state: {
    numCorrect: 0, 
    numIncorrect: 0
  }, 
  mutations: {
    increment (state,payload) {
        state.numCorrect = payload.correct;
        state.numIncorrect = payload.incorrect;
      }
  }
});

Vue file: hello.vue Vue 文件:hello.vue

import store from '../store/store'

  new Vue({
  el: '#app',
  methods: {
    updateText() {
      store.commit("increment", {correct:4,incorrect: 6 })
    }
  }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM