【问题标题】:Vuex state array turning an proxy object when it is mutatedVuex状态数组在变异时转换代理对象
【发布时间】:2020-11-09 14:09:39
【问题描述】:

我开发了一个从数据库获取数据的项目。我使用 Vuex 进行状态管理。

Vuex 存储文件

const store = createStore({
    state: {
        notUser: {
            name: "",
            email: '',
            password: ''
        },
        user: {
            name: '',
            email: '',
            messages: [],
            about: '',
            place: '',
            age: '',
            role: '',
            blocked: false
        },
        problem: {
            title: '',
            content: ''
        },
        problems: [],
        errorMessage: {
            error: false,
            message: '',
            success: false
        },

    },
    mutations: {
        errorHandler(state, error) {
            state.errorMessage.error = true
            state.errorMessage.message = error.response.data.message
        },
        defineUser(state, req) {
            state.user = req.data.user
            console.log(state.user)
        },
        getProblems(state, problems) {
            state.problems = problems
            console.log(state.problems)
        }
    },
    actions: {
        register({ commit }, notUser) {
            axios({
                method: 'post',
                url: 'http://localhost:3000/api/auth/register',
                data: notUser,
                withCredentials: true,
                headers: {
                    "Accept": "application/json"
                  }
              })
              .then(res => {
                this.state.errorMessage.success = true
                  console.log(res.data.data.user)
              })
              .catch(err => {
                this.state.errorMessage.success = false
                console.log(err.response)
                commit('errorHandler', err)
              })
        },
        userLogin({commit}, notUser) {
            axios({
                method: 'post',
                url: 'http://localhost:3000/api/auth/login',
                data: notUser,
                withCredentials: true,
                headers: {
                    "Accept": "application/json"
                  }
              })
              .then(res => {
                this.state.user = res.data.data.user
                this.state.errorMessage.success = true
                console.log(this.state.user)
              })
              .catch(err => {
                this.state.errorMessage.success = false
                console.log(err.response)
                commit('errorHandler', err)
              })
        },
        checkUser({commit}, access_token) {
            axios({
                method: 'post',
                url: 'http://localhost:3000/api/auth/VpW02cG0W2vGeGXs8DdLIq3dQ62qMd0',
                data: access_token,
                withCredentials: true,
                headers: {
                    "Accept": "application/json"
                  }
              })
              .then(res => {
                  console.log(res)
                  commit('defineUser', res)
                return true
              })
              .catch(err => {
                  console.log(err.response)
                commit('errorHandler', err)
                return false
              })
        },
        sendProblem({commit}, problem) {
            axios({
                method: 'post',
                url: 'http://localhost:3000/api/problem/add',
                data: problem,
                withCredentials: true,
                headers: {
                    "Accept": "application/json"
                  }
              })
              .then(res => {
                  console.log(res)
                return true
              })
              .catch(err => {
                  console.log(err.response)
                commit('errorHandler', err)
                return false
              })
        },
        getAllProblems({commit}) {
            axios({
                method: 'get',
                url: 'http://localhost:3000/api/problem/getall',
                withCredentials: true,
                headers: {
                    "Accept": "application/json"
                  }
              })
              .then(res => {
                  commit('getProblems', res.data.data)
                return true
              })
              .catch(err => {
                  console.log(err.response)
                commit('errorHandler', err)
                return false
              })
        }

        // registerUser({commit}, user) {
        //     commit('register', user)
        // }
    },

Vue 组件:使用 Vuex 存储的地方

  computed: {
    ...mapState(["user", 'problems'])
  },
  mounted() {
      return this.getAll()
  },
  methods: {
    ...mapActions(['getAllProblems']),
    goToAdd() {
      this.$router.push('/add')
    },
    async getAll() {
        this.getAllProblems()
    }
  }

问题是当我尝试使用 getAllProblems 操作请求时,它应该使用 getProblems() 改变问题变量。实际上确实如此。但是在问题变量更改后,它会变成一个代理对象。以下是图片:

这是代理对象的图像:

来自数据库的原始数据:


感谢@Hasan Hasanova 的评论 好,知道了。我在安装网站之前调用了 api 并使用函数从存储中获取变量。另一个问题是由于使用了错误的 v-for 语法而发生的。代码如下:

computed: {
    allProblems() { // this is the problems array that i was trying to get
      return this.$store.state.allProblems
    },
    loader() {
      return this.allProblems == null ? true : false
    }
  },
  beforeMount() {
    this.$store.dispatch('getAllProblems', {root: true})
    
  },

这是模板代码:

<div v-if="allProblems.length > 0" class="middle-side">
        <div v-for="(problem) in allProblems" :key="problem.id" class="card">
          <router-link :to="{ name: 'ProblemDetail', params: { id: problem._id, slug: problem.slug }}">
            <div class="card-header">
              <div class="card-header-title">
                <div class="user-image">
                  <img src="../../assets/problem.png" />
                </div>
                <span class="user-name">{{ problem.user.name }}</span>
              </div>

...

谢谢大家。

【问题讨论】:

    标签: vue.js vuex state-management


    【解决方案1】:

    我和你有同样的问题,但是我先解决了这个问题,在getter返回之前将其转换,将其转换为JSON为字符串,然后在返回之前再次将字符串转换为JSON。

    const str = JSON.stringify(data)
    return  JSON.parse(str)
    

    【讨论】:

    • 这个解决方案对我有用,但我希望我有更好的方法来解决我的问题。当我第一次将我的对象存储在 vuex 存储中时,它不是代理对象,然后当我检索它时,它是一个代理对象,然后当我存储更新的对象时,它存储了一个代理对象,打破了我的流程。
    【解决方案2】:

    您想使用mapActions 来调用操作。然后通过状态获取数据,而不是返回函数,因为该操作通过commit 调用突变。


      computed: {
        // you have access to `problems` in the template. Use `v-if` before you `v-for` over the array of problems.
        ...mapState(["user", 'problems'])
      },
      mounted() {
        this.getAllProblems();
      },
      methods: {
        // ...mapActions(['getAllProblems']),
        goToAdd() {
          this.$router.push('/add')
        }
      }
    
    

    【讨论】:

    • 您好,谢谢您的回答。但是当我将 getAllProblems() 与 ...mapActions 一起使用时,没有任何变化。它仍然发送代理对象。
    • 您应该访问状态,而不是依靠操作来返回您的值。
    • 我编辑了类似 i.ibb.co/LRQJMJS/Screenshot-from-2020-11-09-17-37-04.png 的代码。这是真的吗?现在它给出了一个错误:i.ibb.co/WVkn6fW/untitled-3.png 抱歉,我无法准确地理解你想告诉我什么。
    • 您能否显示 api 请求返回的 console.log() 响应,或者您使用的 REST 客户端。只需仔细检查user 是否确实存在于problems &gt; item 对象上。
    • 我已经开始使用 Vue 3 和 Vuex 4。我遇到了完全相同的事情。我不确定这是否是预期的行为。但是当我返回我的状态对象并在模板中访问它时,一切都按预期工作。 @oldner 你的 github 链接坏了。
    【解决方案3】:

    由于某些原因,在将 res.data.data 传递给突变期间发生了这种情况。因此,如果您期望一个单行结果集,您应该这样做:

    POPULATE_THIS_STATE_VAR(state, data) {
        state.thisStateVar = data[0]
    }
    

    ...如果您希望结果集中有一个对象数组,就像您所拥有的那样,您可以这样做:

    POPULATE_THIS_STATE_VAR(state, data) {
         if (data) {
              for (let i = 0; i < data.length; i++) {
                  state.thisStateVar .push(data[i])
              }
         }
    }
    

    【讨论】:

      猜你喜欢
      • 2019-12-05
      • 2019-04-30
      • 2020-08-13
      • 2020-10-22
      • 2021-04-16
      • 2019-04-23
      • 2019-07-20
      • 2020-10-22
      • 2020-11-13
      相关资源
      最近更新 更多