【问题标题】:Vuex State not Reactive without Page reload没有页面重新加载,Vuex 状态不响应
【发布时间】:2020-02-05 06:09:02
【问题描述】:

问题体验需要以下设置: 简单 Nuxt 安装 v2^ 使用 Vuetify 和 Axios

我已经使用真正的后端构建了一个带有许多附加功能的高级应用程序,但我决定在一个简单的 Nuxt 新安装上复制错误,以便能够为你们创建一个 repo。因此,您可能不清楚此演示的功能 - 但在现实生活中,该应用程序正在使用任务和项目。用户必须能够更改每个任务的状态。

如果我无法实现此功能,我无法弄清楚如何进一步使用此应用程序。我的第一个想法是可能是 Nuxt / Vue 的错误 - 但我希望有人能告诉我我错了!

看起来很简单?!好吧,7 天后,我离解决我遇到的这个小 bug 还差得远……

为了便于访问,我已经加载了一个简单的 github 演示,显示了问题所在,只需 3 个步骤即可重现错误。

https://github.com/BarryJamez/not-so-reactive-app.git

步骤:运行“npm run dev”后 - 如下:

第 1 步:从索引页面开始 (http://localhost:3000)

第 2 步:点击“查看任务”

第 3 步:尝试通过按下按钮来更改任务的状态

第 4 步:现在刷新页面,突然之间它就可以工作了。

要重复这个问题,只需导航回主页,刷新(重新加载)页面并从第 1 步重新开始

我尝试了很多东西,但都没有奏效:

**1。我已将包含 cmets 列表的整个子组件移动到父组件中,以消除传递道具的问题。

  1. 我使用了 Vue.set 和 array.splice,而不是仅仅用索引替换数组项

  2. 我已在这些计算数组上启用了观察者并将 'deep' 设置为 true

  3. 我玩过 async 和 await,方法是删除它们并在某些地方添加它们。

  4. 我已使用 $nextTick 函数查看是否是渲染问题

  5. 我已将数组放置在它自己的父级状态属性中(尽管数组中的子元素中的 postId 字段) - 但是我怎么能包含一个状态中的对象 - 一个对象必须有 'child ' 元素。

  6. 我引用了父组件的计算属性,而不是子组件中的道具。**

包含任务的我的页面:

<template>
  <v-container fluid>
    <v-row v-for="task in myTasks" :key="task.id">
      <v-col>
        <v-card class="ma-4">
          <v-card-title>{{task.title}}</v-card-title>
          <v-card-text>
            <p>{{task.description}}</p>
            <p class="blue--text">{{task.status}}</p>
          </v-card-text>
          <v-card-actions>

            <v-btn
              v-if="task.status == 'Active'"
              @click="onChangeStatus(task.id, 'Completed')"
            >
              Complete Task
            </v-btn>

            <v-btn
              v-if="task.status == 'Completed'"
              @click="onChangeStatus(task.id, 'Active')"
            >
              Incomplete Task
            </v-btn>

            <v-btn
                v-if="task.status == 'Active'"
              @click="onChangeStatus(task.id, 'Postponed')"
            >
              Postpone Task
            </v-btn>

            <v-btn
              v-if="task.status == 'Postponed'"
              @click="onChangeStatus(task.id, 'Active')"
            >
              Activate Task
            </v-btn>

          </v-card-actions>
        </v-card>
      </v-col>
    </v-row>
  </v-container>
</template>

<script>
import { mapState } from 'vuex'

export default {
  async fetch({store, route}) {
    await store.dispatch('tasks/getMyTasks', {
      sid: route.params.sid
    })
  },
  methods: {
    onChangeStatus(taskId, status) {
      this.$store.commit('tasks/changeTaskStatus', {
        taskId: taskId,
        status: status,
      })
    }
  },
  computed: {
    ...mapState({
      myTasks: state => state.tasks.myTasks
    })
  }
}

我的商店命名空间为“任务”:

export const store = () => ({
  myTasks: []
})

export const mutations = {
  setMyTasks: (state, tasks) => {
    state.myTasks = tasks
  },
  changeTaskStatus: (state, params) => {
    let index = state.myTasks.findIndex(el => {
      return el.id == params.taskId
    })
    state.myTasks[index].status = params.status
  }
}

export const actions = {
  async getMyTasks (vuexContext, params) {
    try {
      let {data} = await this.$axios.$get('/tasks.json')
      vuexContext.commit('setMyTasks', data)
    } catch (e) {
      console.log(e)
    }
  }
}

我真的不想每次用户登陆时都重新加载页面,因为这违背了 SSR 和 SPA 的目的。

如果您可以选择您的大脑,请查看 Github 上的 repo 并按照上述步骤操作: https://github.com/BarryJamez/not-so-reactive-app.git

【问题讨论】:

  • 我可以看到的主要区别是,在导航到/tasks 时,对tasks.json 的请求发生在客户端。加载 /tasks 新鲜时,请求发生在服务器端

标签: vue.js vuex nuxt.js


【解决方案1】:

您没有在任务存储中定义状态。 在 store/tasks.js 中

export const store = () => ({
  myTasks: []
})

应该是这样的

export const state = () => ({
  myTasks: []
})

【讨论】:

  • 我看了你的两个比较有一段时间才注意到差异!和中提琴,它就像一个魅力。有趣的是,很多其他的东西现在也是反应性的(我正要放弃 Nuxt 因为不是标签所说的!)非常感谢!显然花太多时间看同一件事会让你失明:)
猜你喜欢
  • 2021-09-26
  • 2021-03-20
  • 2021-11-26
  • 2019-11-30
  • 1970-01-01
  • 2020-03-11
  • 1970-01-01
  • 2018-09-04
  • 2017-08-19
相关资源
最近更新 更多