#javascript #vue.js #html5-canvas
#javascript #vue.js #html5-canvas
Вопрос:
Это сложно сформулировать в заголовке, но довольно легко объяснить с помощью некоторых настроек.
У меня есть список компонентов. Каждый компонент в списке выглядит следующим образом:
| [Canvas Preview] Name (Delete button) |
Каждый компонент имеет небольшой элемент canvas, который используется для отображения предварительного просмотра элемента, его имени и кнопки удаления, чтобы удалить его из списка. Список, по которому выполняется итерация v-for, хранится в Vuex.
Используя буквы для представления разных изображений предварительного просмотра, список может выглядеть следующим образом:
| [W] Item 1 (Delete button) |
| [X] Item 2 (Delete button) |
| [Y] Item 3 (Delete button) |
| [Z] Item 4 (Delete button) |
При нажатии кнопки удаления соответствующий элемент удаляется из списка, и список обновляется. Имена обновляются, и щелчок по ним приводит к выбору правильного элемента. Проблема в том, что предварительные просмотры остаются в том же положении. Например, если бы я удалил элемент 2 (с предварительным просмотром X) из списка выше, у меня был бы следующий список:
| [W] Item 1 (Delete button) |
| [X] Item 3 (Delete button) |
| [Y] Item 4 (Delete button) |
Предварительные просмотры являются WXY, когда они должны быть WYZ, поскольку X был удален. В основном холсты остаются в том же порядке, и один просто удаляется с конца, независимо от того, откуда был удален элемент.
Я могу придумать пару хакерских способов перерисовки всех холстов при удалении элемента, но мне было интересно, есть ли лучшее решение.
РЕДАКТИРОВАТЬ: Вот код, который удаляет элемент
Кнопка удаления на элементе отправляет событие в компонент списка
<button @click="deleteAsset">Delete</button>
deleteAsset(event){
event.stopPropagation();
this.isRenaming = false;
this.$emit('deleteAsset', this.asset);
},
Затем оболочка отправила действие Vuex
deleteAsset(asset){
this.$store.dispatch('GameData/deleteAsset', {category: asset.category_ID, id: asset.ID});
this.updateAsset();
},
Действие Vuex и мутация
//Action
deleteAsset({commit}, {category, id}){
commit('deleteAsset', {category, id})
}
//Mutation
deleteAsset: (state, {category, id}) => {
let curList = getList();
let hasFound = false;
for (let i = 0; !hasFound amp;amp; i < curList.length; i ){
if (curList[i].ID == id){
curList.splice(i, 1);
hasFound = true;
}
}
}
Остальные данные верны, так как я добавил функцию быстрого тестирования для печати текущего идентификатора и данных по щелчку, и все печатается правильно. Похоже, что это просто элемент canvas, который не меняется.
ПРАВКА 2: код vue
//List
<Asset
ref="assets"
v-for="asset in selectedList"
:key="asset.cat_ID"
:asset="asset"
:defaultIcon="selected_category.icon"
@deleteAsset="deleteAsset"
@selectAsset="selectAsset"/>
//Asset code
<template>
<div ref="asset" class="asset" :class="{selected : isSelected}" @click="selectAsset">
<div class="leftFloat">
<canvas v-show="hasThumb" class="thumbnail" ref="thumbNail" width="20" height="20">Test</canvas>
<img v-if="!hasThumb" class="thumbnail assetIcon" :src="require(`@/${defaultIcon}.svg`)" />
<div v-if="isRenaming">
<input ref="renameText" v-model="asset.name" type="text" />
</div>
<div v-else>{{asset.name}}</div>
</div>
<div class="rightFloat">
<button class="rightButton" @click="deleteAsset">
<img class="rightIcon" src="@/assets/trash.svg" />
</button>
</div>
</div>
</template>
Комментарии:
1. пожалуйста, добавьте коды, как вы удаляете элемент из списка.
2. Вероятно, это
:key
проблема. Как вы отображаете данные?3. Вот и все! Я использовал идентификатор категории (
asset.cat_id
) вместо идентификатора ресурса (asset.ID
) для ключа. Раньше у меня были проблемы с Android и другими подобными фреймворками, где у него были проблемы с «повторным использованием», поэтому я предположил, что это аналогичная проблема. Странно, как имена обновлялись правильно, хотя никогда бы не догадался, что это была проблема : key. Огромное спасибо
Ответ №1:
Предполагая, что cat_ID
может быть назначен более чем одному ресурсу, вы столкнетесь с проблемами, используя его как key
поскольку Vue не сможет обнаружить изменения списка, если cat_ID
повторяется в любом из ваших selectedList
активов.
Поскольку у ваших активов есть ID
свойство, вы должны использовать его в своем key
<Asset
ref="assets"
v-for="asset in selectedList"
:key="asset.ID"
:asset="asset"
:defaultIcon="selected_category.icon"
@deleteAsset="deleteAsset"
@selectAsset="selectAsset"/>
Смотрите key
key
Специальный атрибут в основном используется как подсказка для алгоритма виртуального DOM Vue для идентификации VNodes при сравнении нового списка узлов со старым списком. Без ключей Vue использует алгоритм, который минимизирует перемещение элементов и пытается как можно больше исправлять / повторно использовать элементы того же типа на месте. С помощью keys он изменит порядок элементов на основе изменения порядка ключей, а элементы с ключами, которые больше не присутствуют, всегда будут удалены / уничтожены.
Комментарии:
1. Именно это, спасибо! Поскольку имена менялись, это действительно сбивало меня с толку, и я никогда бы не догадался, что это
:key
проблема