Vue.js 3-如何在Vue组件之间传递数据并同时更新两个视图?

问题描述

我尝试了以下方法。 请注意parent.vue中的注释行,它甚至没有为我提交新状态。 但是,也许有人可以引导我找到由多个组件共享的全局状态的更好解决方案?

main.js

import { createApp } from 'vue'
import App from './App.vue'
import { createStore } from 'vuex'

const app = createApp(App);
export const store = createStore({
    state: {
        textProp: 'test',count: 1
    },mutations: {
        setState(state,newState) {
            console.log('setState');
            state = newState;
        }
    },getters: {
        getAll: (state) => () => {
            return state;
        }
    }

});
app.use(store);
app.mount('#app')

parent.vue

<template>
  <div class="parent">
    <div class="seperator" v-bind:key="item" v-for="item in items">
      <child></child>
    </div>
    <button @click="toonAlert()">{{ btnText }}</button>
    <button @click="veranderChild()">Verander child</button>
  </div>
</template>


<script>
import child from "./child.vue";
import {store} from '../main';

export default {
  name: "parent",components: {
    child,},store,data: function () {
    return {
      items: [
        {
          id: 1,valueText: "",valueNumber: 0,{
          id: 2,{
          id: 3,],};
  },props: {
    btnText: String,methods: {
    toonAlert() {
      alert(JSON.stringify(this.$store.getters.getAll()));
    },veranderChild() {
       console.log('child aan het veranderen (parentEvent)');
       this.$store.commit('setState',{ // This is especially not working.
             textProp: 'gezet via de parent',count: 99
         })
       this.$store.commit({type: 'setState'},{
         'textProp': 'gezet via de parent','count': 99
          });
    },};
</script>

<style>
.seperator {
  margin-bottom: 20px;
}

.parent {
  /* background: lightblue; */
}
</style>

child.vue

<template>
  <div class="child">
    <div class="inputDiv">
      text
      <input @change="update" v-model="deText" type="text" name="deText" />
    </div>
    <div class="inputDiv">
      nummer
      <input v-model="hetNummer" type="number" name="hetNummer" />
    </div>
    <button @click="toonState">Toon huidige state</button>
  </div>
</template>

<script>

import {store} from '../main';

export default {
  name: "child",data: function() {
    return {
      'hetNummer': 0
    }
  },methods: {
    update(e) {
      let newState = this.$store.state;
      newState.textProp = e.target.value;
      // this.$store.commit('setState',newState);
    },toonState()
    {
      console.log( this.$store.getters.getAll());
    }
  },computed: {
    deText: function() {
      return '';
      // return this.$store.getters.getAll().textProp;
    }
  }
};
</script>

<style>
.inputDiv {
  float: right;
  margin-bottom: 10px;
}
.child {
  max-width: 300px;
  height: 30px;
  margin-bottom: 20px;
  /* background: yellow; */
  margin: 10px;
}
</style>

解决方法

您对与Vue / Vuex无关的JavaScript有误解。这没有达到您的期望:

state = newState;

解决方案(TL; DR)

setState(state,newState) {
  Object.assign(state,newState);
}

合并新属性而不是设置state变量。

说明

    JavaScript中的
  • 对象变量是引用。这就是为什么如果您有多个变量引用同一个对象,而您更改了一个对象的属性,则它们都会发生变化。它们都只是引用内存中的同一对象,不是克隆对象。

上面的state变量作为对Vuex状态对象的引用开始。因此,当您更改其属性时,也会同时更改Vuex的状态属性。很好。

但是,当您将整个变量(不仅仅是一个属性)更改为其他变量时,它不会变异原始引用的对象(即Vuex的状态)。它只是断开引用链接,并为newState对象创建一个新链接。因此,Vuex状态根本不会改变。这是一个更简单的demo

意见

避免使用此模式,而是在state上创建对象属性。然后,您可以执行state.obj = newState

,

您应该使用传播运算符...来更改状态,如下所示:

 state = { ...state,...newState };

LIVE EXAMPLE

但是我建议您以语义方式使您的商店更井井有条,您所在州的每个属性都应有自己的setteraction,getter等同于选项API中的计算属性,基于多个状态属性。

export const store = createStore({
  state: {
   
    count: 1
  },mutations: {
    SET_COUNT(state,_count) {
      console.log("setState");
      state.count=_count
    },INC_COUNT(state) {
     
      state.count++
    }
  },getters: {
    doubleCount: (state) => () => {
      return state.count*2;
    }
  }
});

**注意:**无需从每个孩子的main.js导入商店,因为可以在选项api中使用this.$store来使用商店,但是如果您使用的是api,则可以使用{ {1}}如下:

useStore

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...