2017-06-27 16 views
1

問題についてのベストプラクティス(あるいはゴーする練習)リストとコンポーネントは、データの変更後に更新されない - (VueJS + VueX)

私はリスト(元to-doリストを。)持っています。実際のアプローチは次のとおりです。

  • 私の親コンポーネントでは、私は 'store.todos'配列を作成します。 ゲッターを使用して、すべてのTo-Doを取得し、v-for ループを使用してリストを反復処理します。

  • すべてのアイテムはコンポーネントであり、私はそのアイテムを支柱として送信します。

  • このコンポーネントでは、 "done"フラグを更新するロジックがあります。そしてこの要素は、フラグの "状態"に基づいてチェックボックスを表示します。それが実行されると、dbへのアクションが実行され、ストアの状態が更新されます。

代わりに、私必要があります。

  • は、各リスト項目ゲッターを持ち、かつ唯一の子コンポーネントの下IDを送信するようにしたことがありますか?

すべてがうまくいきますが、予定リストに新しいアイテムを追加すると、完了したとマークするとこのアイテムは更新されません。私は子コンポーネント内の小道具ではなくゲッターを使用しているため、この問題がある場合、私は疑問に思う

コード:

店舗

const state = {  
    tasks: [] 
} 

const mutations = {  
CLEAR_TASKS (state) { 
    state.tasks = []; 
}, 
SET_TASKS (state, tasks) { 
    state.tasks = tasks; 
}, 
ADD_TASK (state, payload) { 
    // if the payload has an index, it replaces that object, if not, pushes a new task to the array 
    if(payload.index){   
     state.currentSpaceTasks[payload.index] = payload.task; 
     // (1) Without this two lines, the item doesn't update 
     state.tasks.push(''); 
     state.tasks.pop(); 
    } 
    else{   
     state.tasks.push(payload.task); 
    } 
}, 
SET_TASK_COMPLETION (state, task){ 

    let index = state.tasks.findIndex(obj => obj.id == task.id); 
    state.tasks[index].completed_at = task.completed_at; 
} 
} 

const getters = { 
(...) 
getTasks: (state) => (parentId) => {   
    if (parentId) { 
     return state.tasks.filter(task => task.parent_id == parentId); 
    } else {    
     return state.tasks.filter(task => !task.parent_id); 
    } 
} 
(...) 
} 

const actions = { 
(...) 
/* 
* Add a new Task 
* 1st commit add a Temp Task, second updates the first one with real information (Optimistic UI - or a wannabe version of it) 
*/ 
addTask({ commit, state }, task) {   
     commit('ADD_TASK',{ 
      task 
     }); 
    let iNewTask = state.currentSpaceTasks.length - 1; 

axios.post('/spaces/'+state.route.params.spaceId+'/tasks',task).then(
     response => { 
      let newTask = response.data;  
      commit('ADD_TASK',{ 
       task: newTask, 
       index: iNewTask 
      }); 
     }, 
     error => { 
      alert(error.response.data); 
     }); 

}, 
markTaskCompleted({ commit, dispatch, state }, task){ 

     console.log(task.completed_at); 
     commit('SET_TASK_COMPLETION', task); 
     dispatch('updateTask', { id: task.id, field: 'completed', value: task.completed_at }).then(
      response => { 
       commit('SET_TASK_COMPLETION', response.data); 
      }, 
      error => { 
       task.completed_at = !task.completed_at; 
       commit('SET_TASK_COMPLETION', task); 
      }); 

}, 
updateTask({ commit, state }, data) {    
    return new Promise((resolve, reject) => {  
     axios.patch('/spaces/'+state.route.params.spaceId+'/tasks/'+ data.id, data).then(
     response => { 
      resolve(response.data); 
     }, 
     error => { 
      reject(error);  
     }); 
    }) 
} 

} 

そして、基本的に、これは私の親と子のコンポーネントは次のとおりです。

タスクリストコンポーネント(それはゲッターからタスクをロードする) (...)

<task :task = 'item' v-for = "(item, index) in tasks(parentId)" :key = 'item.id"></task>    
(...) 

タスクコンポーネントは「チェックボックス」(Fontawesomeを使用)を表示します。完了したかどうかに応じて、チェックされているかされていないかがチェックされます。

この手順では正常に動作します:

  1. アクセスタスクリスト
  2. マーク1つの既存のアイテムに行わとして - チェックボックスが

をチェックされている。この手順では、

  1. 新しいタスクを追加に失敗しました(これは、最初に '一時的な'アイテムを追加するaddタスクを起動し、ajaxを返した後、reaで更新しますl情報(イドなど)。 IDを持っていない間、タスクはチェックボックスの代わりに読み込みを表示し、更新後にチェックボックスを表示します - これは機能します!
  2. 新しく追加されたタスクを確認します。要求を送信し、アイテムとDBを更新します。しかし、チェックボックスは更新されていません:(
+0

ゲッターのデザインは、私は信じて完全にあなた次第です。最後の質問について - 実際のコードなしで言うのは難しいです。おそらく、あなたは 'v-for'要素に一意の' key'属性を割り当てなかったでしょう(更新がテンプレートに反映されていない場合)。 – wostex

+0

@wostex私は今朝これを試していましたが、運が無ければ、公正であるために、最初にコンセプトを得ていないので、正しく実行しませんでした。今夜それをチェックし、それが解決すれば教えてください! –

+0

問題が解決しない場合は、関連するコード部分を質問に追加してください。デバッグに役立ちます。 – wostex

答えて

2

Vue.jsドキュメントを掘り下げた後、修正することができました。

Vue.jsとVuexは、元のオブジェクトになかったプロパティに対して反応性を拡張しません。

例えば、配列に新しいアイテムを追加するには、あなたがこれをしなければならない。ここで

// Vue.set 
Vue.set(example1.items, indexOfItem, newValue) 

さらに詳しい情報: https://vuejs.org/v2/guide/reactivity.html

、ここで:https://vuejs.org/v2/guide/list.html#Caveats

最初にそれだけでは解決で問題の一部私は配列にアイテムをプッシュした後に使用される "ハック"を必要としません(リストを再ロードするために空のオブジェクトをプッシュしてポップする)

これを念頭に置いて、 getTasksでは、リストにはcompleted_atを含むすべてのフィールドがありますが、新しい項目を保存した後は、設定されたフィールドのみが返されました(completed_atは作成時にnull)。つまり、Vue.jsはこのプロパティを追跡していませんでした。

サーバー側(Laravel、btw)が返すプロパティを追加しましたが、すべて正常に機能します。

誰もがこれ以外の私のコードについてのポイントを持っている場合は、追加して自由に感じる:)

おかげでみんな

+0

この問題の追加情報は、私と全く同じです:https://github.com/vuejs/vuex/issues/654 –

関連する問題