2017-07-11 4 views
0

私はVueが反応性の高いコンテンツを更新するのが遅いという問題があります。Vueリアクティブコンテンツをすばやく更新するにはどうすればよいですか?

ユーザーがリストからアイテムを選択するようにします。アイテムが選択されているときは、マークする必要があります。テストのために、私はちょうど選択された項目の周りに境界を設定しています。問題は複数のアイテムがある場合、Vueが選択したアイテムのクラスを更新(反応)するのに非常に時間がかかると感じています。

だから私は、次のようになります簡単な反応店舗があります。私は多くの項目が含まれます単純なリストをレンダリング私のコンポーネントにこの店を渡す

export default new Vuex.Store({ 
    state: { 
    selections: [] 
    }, 
    mutations: { 
    set_selections (state, sel) { 
     state.selections = sel; 
    } 
    } 
}) 

を。

<p v-for="item in items"> 
    <span v-bind:class="{ 'is-selected': isSelected(item) }" v-on:click="onSelect(item)"> 
     {{ item.name }} 
    </span> 
    </p> 

だから各項目は、私が追加一意のIDを持つことになります/私のVuexストア状態、選択から削除します。

onSelect: function(item, event){ 
    let itemId = item._id; 
    let sel = this.selections; 
    if (sel.indexOf(itemId) !== -1) { 
     var index = sel.indexOf(itemId); 
     sel.splice(index, 1); 
    } else { 
     sel.push(itemId); 
    } 
    this.$store.commit("set_selections", sel); 
}, 

ところ、

selections: function() { 
    return this.$store.state.selections; 
} 

フェッチ計算されたプロパティです現在の選択。

項目が選択されているかどうかを確認するため、DOM要素に「ある-選択し、」クラスを追加し、以下のように見える方法:

isSelected: function(item){ 
    let itemId = item._id; 
    let sel = this.selections; 
    if (sel.indexOf(itemId) !== -1) { 
     return true; 
    } 
    return false; 
}, 

問題を 私はで多くのアイテムを持っている場合私のリスト反応的な内容は非常に鈍いと感じます。アイテムをクリックすると、アイテムがマークされる前に約500ms〜1秒かかります。 (私は非常に多くのアイテムを持っていることに注意してください)。私はおそらく何か間違っていますか? v-forを使用してループしているので、時間がかかる可能性があるすべてのアイテムに対してVueがisSelectedメソッドを再計算する必要があることを理解しています。

もちろん私はクラスをonClickイベントで直接追加/削除することができましたが、その後Vueを使用している点がすべて緩んでいます。どのようにこの問題に対処しますか?

+0

Vueのは、リスト全体を再描画する必要がないように、これは、ほとんどのコンポーネントにあなたのリスト項目をリファクタリングすることによって解決されます。 – Bert

+0

しかし、どうしたらいいですか?私はまだそれらをレンダリングするために各項目をループする必要がありますか?代わりに "isSelected"がコンポーネントで計算された場合、更新されるときに各アイテムで "isSelected"が呼び出されます。 – Euklides

+0

もちろん、変更されたコンポーネントだけを再描画する必要があります。リストのすべてではありません。実際の例をフィドル/ペンでまとめると、リファクタリングに取り組むことができます。 – Bert

答えて

1

あなたが1000個のコンポーネント/アイテムでこれを実行している場合、選択配列の反復処理が高価になる可能性があるため、リストの更新が遅いと思います。

また、コメントkeyに記載されているように、結合も速度を改善することができる(速度差は試験されていない)。

私のデモでは、選択オブジェクトを作成してプロパティを確認した後、最良の結果がselectedにありました。

さらに、計算されたプロパティとしてselectedをチェックする方が速いです。

計算されたプロパティの場合、1000項目のリストを持つ項目を選択するには約200msかかります。選択方法を使用すると、約450msかかるでしょう - それがなぜ非常に遅いのか正確にはわかりません。ここで

は(クローム59.0.3071.115(64ビット)でテスト - i5-6200/8ギガバイトRAM/Win10)1つの選択イベントの200msのためのパフォーマンスのスクリーンショットです:現時点では Screenshot 200ms

、これが私です最も速いバージョン。私はまた、選択を表示するために0.5から1秒で開始しました。

以下のデモをご覧ください。fiddleです。

const listItem = { 
 
\t props: ['item'], 
 
\t template: ` 
 
    \t <li :class="{ 'is-selected': selected }" @click="$emit('selected', item)"> 
 
     {{ item.name }} 
 
    </li> 
 
    `, 
 
    computed: { 
 
    \t ...Vuex.mapState(['selections']), 
 
    selected() { 
 
    \t // 200ms time to mark item for click with 1000 list items - clicked Test 326 
 
    \t return this.selections[this.item.id] !== undefined; // object property check is fast 
 
    } 
 
    }, 
 
    methods: { 
 
    \t selected() { 
 
    \t // 450ms to mark selection 
 
    \t //console.log('selected', this.selections, !!this.selections[this.item.id]); 
 
     // slightly slower than computed property 
 
    \t return this.selections[this.item.id] !== undefined; // object property check is fast 
 
    \t // array --> slow because another iteration for each component required 
 
    \t //this.selections.indexOf(this.item) !== -1 
 
    } 
 
    } 
 
}; 
 

 
const list = { 
 
\t props: ['items'], 
 
\t template: ` 
 
    \t <ul> 
 
    \t <list-item 
 
     \t v-for="item in items" 
 
     :item="item" 
 
     @selected="select" 
 
     :key="item.id"></list-item> 
 
    \t </ul> 
 
    `, 
 
    components: { 
 
    \t listItem 
 
    }, 
 
    methods: { 
 
    \t select(item) { 
 
    \t this.$store.commit('set_selection', item) 
 
    } 
 
    } 
 
}; 
 

 
const store = new Vuex.Store({ 
 
\t state: { 
 
    selections: [] 
 
    }, 
 
    mutations: { 
 
    set_selection (state, item) { 
 
     //state.selections = sel; 
 
     console.log('clicked', item, state.selections[item.id]); 
 
     
 
     if (state.selections[item.id]) { 
 
     \t // in object --> remove from selection 
 
     \t //let {[item.id]: deleted, ...newState} = state; 
 
     state.selections[item.id] = undefined; 
 
     } 
 
     else { 
 
     \t // not in object --> add item 
 
     \t state.selections = { 
 
     \t ...state.selections, 
 
     \t [item.id]: item 
 
     } 
 
     } 
 
     // console.log(state.selections, !!state.selections[item.id]); 
 
     
 
     /* 
 
     --> array approach is slow 
 
     if (state.selections.indexOf(item) === -1) 
 
     { 
 
     \t // not in list --> push to list 
 
     \t state.selections.push(item); 
 
     } 
 
     else { 
 
     \t // in list --> remove selection 
 
     \t state.selections.pop(item); 
 
     }*/ 
 
    } 
 
    } 
 
}) 
 

 
function createItems(count) { 
 
\t let items = []; 
 
    for(let i=0; i< count; i++) { 
 
    \t items.push({ 
 
    \t id: i, 
 
     name: 'Test ' + i 
 
    }); 
 
    } 
 
    return items; 
 
} 
 

 
new Vue({ 
 
\t el: '#app', 
 
    store, 
 
    data() { 
 
    \t let items = createItems(1000); 
 
    \t return { 
 
    \t items 
 
    }; 
 
    }, 
 
    components: { 
 
    \t list 
 
    } 
 
})
.is-selected { 
 
    background-color: red; 
 
    border: 1px solid red; 
 
} 
 

 
ul { 
 
    list-style-type: none; 
 
} 
 
li { 
 
    cursor: pointer; 
 
} 
 

 
li:hover { 
 
    border: 1px solid gray; 
 
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.js"></script> 
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/vuex/2.3.1/vuex.js"></script> 
 
<div id="app"> 
 
    <list :items="items"></list> 
 
</div>

+0

その答えをありがとう!配列を辞書に変更した後、Vueに 'Vue.set(state.selections、item.id、item)'を使って変更に反応させなければなりませんでした。 私はあなたのfiddleを修正しました:https://jsfiddle.net/9o17yheq/1/ しかし、私はまだそれが辞書であるときに約5項目を選択した後にとても遅い理由を理解できませんか? – Euklides

+0

ようこそ。私はそれが5つ以上の選択の後に遅くなっているのを見ることができません。 (私は時間を測定していませんが、それは遅くはないようです)。どのブラウザでその動作を見たことがありますか? – AWolf

+2

これは本当にスピードを上げるものです。コンポーネントを起動するときに辞書内のすべてのキーを事前に割り当てます。それはすべての違いになります。私は今、どん​​な遅れも見ることができません。 https://jsfiddle.net/9o17yheq/2/ – Euklides

関連する問題