Vue、Vuex、JavaScript:includes() 无法按预期工作

Posted

技术标签:

【中文标题】Vue、Vuex、JavaScript:includes() 无法按预期工作【英文标题】:Vue, Vuex, JavaScript: includes() does not work as expected 【发布时间】:2019-11-24 09:12:43 【问题描述】:

如果数组中不包含具有相同 id 的对象,我想将一些对象存储在数组中。无论如何,一切正常,直到我开始一次添加多个对象。

这里是使用Vuex的相关代码:

// filter function to check if element is already included
function checkForDuplicate(val) 
    for( let sessionItem of state.sessionExercises ) 
        return sessionItem._id.includes(val._id);
    
;

// related array from vuex state.js
sessionExercises: [],


// vuex mutation to store exercises to session exercises
storeSessionExercises: (state, payload) => 
    // Pre filtering exercises and prevent duplicated content
    if( checkForDuplicate(payload) === true ) 
        console.log("Exercise ist bereits für session registriert!");
     else 
        state.sessionExercises.push(payload);
    
,


// Related vuex action
storeSessionExercises: ( commit , payload) => 
    commit("storeSessionExercises", payload)
,

正如我之前写的,只要我添加一个对象,一切正常,checkForDuplicate() 将找到重复的对象并拒绝推送到数组。

现在有一种情况,我想将一组对象推送到数组,我通过数据库请求执行此操作,循环输出,提取对象并通过与我所做的相同的函数推送它们单个对象:

// get user related exercises from database + clear vuex storage + push db-data into vuex storage
addSessionWorkout: ( commit, dispatch , payload) => 
    axios.post(payload.apiURL + "/exercises/workout", payload.data,  headers:  Authorization: "Bearer " + payload.token  )
    .then((result) => 
        // loop through output array and 
        for( let exercise of result.data.exercises ) 
            // push (unshift) new exercise creation to userExercises array of vuex storage
            dispatch("storeSessionExercises", exercise)
        ;
    )
    .catch((error) => 
        console.error(error)
    );
,

推送也可以正常工作,但“过滤功能”却没有发挥作用。它将过滤第一个对象并拒绝将其推送到数组中,但是如果有第二个对象,即使已经包含相同的对象(相同的 ID),也会将其推送到数组中,我在这里看不到什么! ?让我疯了! :D

我理解它就像循环会将每个对象放入 checkForDuplicate() 并查看是否有重复它应该输出 true,因此该对象不会被推入数组。如果有人看到我目前不告诉我的内容。

【问题讨论】:

【参考方案1】:

错误是您的过滤功能。你想循环你的 sessionExercises 并且只返回 true 如果它们中的任何一个匹配。但是,此时您返回第一次检查的结果。您的循环将始终只运行一次。

选项 1:仅在匹配时返回

function checkForDuplicate(val) 
    for( let sessionItem of state.sessionExercises ) 
        if (sessionItem._id.includes(val._id)) 
            return true;
        
    
    return false;
;

选项 2:使用 es6 过滤器

storeSessionExercises: (state, payload) => 
    var exercises = state.sessionExercises.filter(ex => (ex._id.includes(payload._id)));
    if(exercises.length) 
        console.log("Exercise ist bereits für session registriert!");
     else 
        state.sessionExercises.push(payload);
    

【讨论】:

不再只见树木不见森林! :) 那当然完全解决了它!非常感谢。【参考方案2】:

我会更改 addSessionWorkout 操作,我会创建一个包含新旧条目的新练习数组,然后更新状态。

// related array from vuex state.js
sessionExercises: [],


// vuex mutation to store exercises to session exercises
storeSessionExercises: (state, payload) => 
    state.sessionExercises = payload;
,


// Related vuex action
storeSessionExercises: ( commit , payload) => 
    commit("storeSessionExercises", payload)
,


addSessionWorkout: async(
  commit,
  dispatch,
  state
, payload) => 
  const result = await axios.post(payload.apiURL + "/exercises/workout", payload.data, 
    headers: 
      Authorization: "Bearer " + payload.token
    
  )

  try 
    const newExercices = result.data.exercises.reduce((acc, nextItem) => 
      const foundExcercise = acc.find(session => session.id === nextItem.id)
      if (!foundExcercise) 
        return [...acc, nextItem]
      
      return acc
    , state.sessionExercises)
    dispatch("storeSessionExercises", foundExcercise)
   catch (e) 
    console.error(error)
  
,

【讨论】:

以上是关于Vue、Vuex、JavaScript:includes() 无法按预期工作的主要内容,如果未能解决你的问题,请参考以下文章

javascript vue js vuex突变

javascript 与Vue的通量 - Vuex

javascript vue vuex mapActions和mapMutations

javascript Vue Vuex打字稿模块操作导出

如何在单独的非 Vue 组件、JavaScript/TypeScript 文件中访问 Vuex 状态?

vue 简单版状态机(vuex)