如何从 vuex-store 更新 vue 子组件

Posted

技术标签:

【中文标题】如何从 vuex-store 更新 vue 子组件【英文标题】:how can I update a vue child-component from the vuex-store 【发布时间】:2021-12-25 14:39:15 【问题描述】:

我的应用程序显示一个窗口,玩家可以在其中输入姓名和密码进入

当玩家存在并且有卡片时,我也想显示卡片。 当玩家存在时,我让卡片可见。然后在“创建”中我调用 fetchSpelerCards。这是成功的,但在 VUE 控制台中显示为待处理...

我希望有经验的 vue 用户阅读本文并可以帮助我提供提示、参考或解释。

为此,我有以下代码:

 <h2>Meld je aan</h2>
    <form @submit.prevent="register" class="mb-3"> 
        
        <div class="form-group">
            <input type="text" class="form-control m-2" placeholder="naam" v-model="name">
        </div>

        <div class="form-group">
            <input type="text" class="form-control m-2" placeholder="kies inlogcode" v-model="pass_code">     
        </div>

        <button type="submit" @click="checkSpeler()"  class="btn btn-primary btn-block" style="color:white">Save</button>
    </form>
    <p class="alert alert-danger" v-if="errorMessage !== ''"> errorMessage </p>
    <p class="alert alert-success" v-if="successMessage !== ''"> successMessage </p>
    <CardsSpeler v-if="spelerCorrect"></CardsSpeler>
    
</div>
</template>

组件如下所示:

 <h2>Cards 1</h2>
    <form @submit.prevent="addCard" class="mb-3"> 
        <div class="form-group">
            <input type="text" class="form-control" placeholder="title" v-model="card.title">
        </div>

        <div class="form-group">
            <textarea  class="form-control" placeholder="description" v-model="card.description">
            </textarea>
        </div>

        <div>
            <input type="file" v-on:change="onFileChange" ref="fileUpload" id="file_picture_input">
        </div>

        <button type="submit" class="btn btn-primary btn-block" style="color:white">Save</button>
    </form>
    <div class="card card-body mb-2" v-for="card in cards" v-bind:key="card.id">   
        <h3> currentSpelerCard.title   </h3>
        <p> currentSpelerCard.description</p>
        <img class="img-circle" style="width:150px" v-bind:src="currentSpelerCard.picture" >


    </div>
</div>
</template>

<script>
import  mapState, mapActions  from 'vuex';

export default 
    mounted()
        console.log('component mounted');  
    ,
    computed: 
        ...mapState([
        'currentSpeler' ,'currentSpelerCard'
        ]), 
    ,
    data() 
        return
            cardExists:false,
            successMessage:'',
            errorMessage:'',
        

    ,
    created()
      this.fetchSpelerCards();
    ,
    methods: 

        ...mapActions([  'getGames', 'addGame', 'fetchSpelerCards'  ]),

        fetchSpelerCards()
            
                this.$store.dispatch('fetchSpelerCards', this.currentSpeler.speler.id )
                .then(res =>  
                    this.cardExists = true;
                    this.successMessage = res;
                    console.log(res);
                )
                .catch(err => 
                    this.errorMessage = err;
                    this.cardExists = false;
                );
            
        ,

对应的action,在actions.js中是:

export const fetchSpelerCards = (commit, speler_id) => 
    return new Promise((resolve, reject) =>      
        let status = '';
        let data =;
        fetch(`api/cardsBySpeler/$speler_id`)
        .then(res => 
            status = res.status;
            data = res.json(); 
        )
        .then(res=>
            if ( status === 200) 
                commit('SET_PLAYER_CARD', data);
                resolve('Kaart gevonden');
            
            else 
                reject('Er is geen kaart beschikbaar')
            
        );
    )


在我看到的 vuex-store 中(使用 chrome 浏览器的 VUE 插件查看):

currentSpelerCard: Promise

然而,fetch 命令的响应是成功的,并且卡被拉入,正如我在控制台中看到的那样:状态 200,我可以看到名称、标题、图像地址等。

我的假设是,当承诺最终解决时,商店会更新并且卡可用,因为:

computed:   ...mapState([  'currentSpeler' ,'currentSpelerCard' ]),

谁能帮助我并解释我做错了什么?

【问题讨论】:

请在沙盒项目中使用codesandbox.io,以便我们进行调试。 你能分享改变currentSpelerCard的变异代码吗? 【参考方案1】:

fetchSpelerCards 在 Vuex 中提交 SET_PLAYER_CARDdata,这将是一个未决的承诺。你需要等待承诺。

您可以通过几种不同的方式解决此问题。

制作函数asyncawait res.json() 将是最简单的。

...
  fetch(`api/cardsBySpeler/$speler_id`)
    .then(async res => 
      status = res.status;
      data = await res.json(); 
    )
...

【讨论】:

非常感谢!这行得通。我只是不明白为什么这是必要的。在原始脚本中,我在 .then() 函数中提交,所以我希望这仅在承诺解决后才会发生。我哪里错了,我在这里想念什么?【参考方案2】:

尝试重命名您的方法,然后等待完成:

async mounted()
  await this.initSpelerCards();
,
methods: 
  ...mapActions([ 'getGames', 'addGame', 'fetchSpelerCards' ]),

  initSpelerCards()
    this.fetchSpelerCards(this.currentSpeler.speler.id)
      .then(res =>  
        this.cardExists = true;
        this.successMessage = res;
        console.log(res);
      )
      .catch(err => 
        this.errorMessage = err;
        this.cardExists = false;
      );
  ,

【讨论】:

以上是关于如何从 vuex-store 更新 vue 子组件的主要内容,如果未能解决你的问题,请参考以下文章

15VUEX-Store

如何在 Vue JS 中将更新的值从父组件发送到子组件?

Vue子组件中 data 从props中动态更新数据

Vue父组件向子组件传递一个动态的值,子组件如何保持实时更新实时更新?

如何使用 Vue.js 在父组件中更新子组件中的数据?

Vue 道具没有在子组件中正确更新