Почему я не могу часто устанавливать данные
Давайте сначала популяризируем, что делает setData:
Во время передачи данных уровень логики выполнит JSON.stringify для удаления непередаваемой части данных setData, а затем отправит данные на уровень представления. В то же время уровень логики также объединит поля данных, заданные setData, с данными, чтобы разработчики могли использовать this.data для чтения измененных данных.
Поэтому, если он вызывается часто, представление будет постоянно обновляться, блокируя взаимодействие с пользователем и вызывая проблемы с производительностью.
Однако частые вызовы — распространенный сценарий разработки. Можно ли отложить обновление представления при частых вызовах?
Ссылаясь на Vue, мы можем знать, что каждая операция назначения Vue не обновляет представление напрямую, а кэширует его в очереди обновления данных, обновляет его асинхронно, а затем запускает рендеринг.В настоящее время несколько назначений будут отображаться только один раз.
let newState = null;
let timeout = null;
const asyncSetData = ({
vm,
newData,
}) => {
newState = {
...newState,
...newData,
};
clearTimeout(timeout);
timeout = setTimeout(() => {
vm.setData({
...newState,
});
newState = null
}, 0);
};
из-заАсинхронный код выполняется после синхронного кода, поэтому, когда вы устанавливаете newState с asyncSetData несколько раз, newState будет кэшироваться и setData асинхронно один раз
Но в то же время эта схема принесет и новую проблему,Синхронный код блокирует отрисовку страницы.
Синхронный код блокирует отрисовку страницыПроблема на самом деле существует в браузере, но в апплете, из-за логики и двухпоточной архитектуры представления, логика не будет блокировать отрисовку представления, что является преимуществом апплета, но эта схема потеряет это преимущество.
Нельзя есть и рыбу, и медвежью лапу!
Для страниц потока информации, что делать, если данных слишком много
Набор данных за один раз не может превышать 1024 КБ, старайтесь не устанавливать слишком много данных за один раз.
Обычно мы извлекаем данные подкачки newList и добавляем их в массив, обычно записывается так:
this.setData({
list: this.data.list.concat(newList)
})
По мере увеличения числа пейджингов список будет постепенно увеличиваться, при превышении 1024 кб программа сообщитexceed max data size
ошибка.
Чтобы избежать этой проблемы, вместо переназначения всего списка мы можем напрямую изменить элемент списка:
let length = this.data.list.length;
let newData = newList.reduce((acc, v, i)=>{
acc[`list[${length+i}]`] = v;
return acc;
}, {});
this.setData(newData);
Это кажется немного громоздким.Чтобы упростить операцию, мы можем изменить структуру данных списка с одномерного массива на двумерный массив:list = [newList, newList]
, для каждого пейджинга вы можете напрямую назначить весь новый список в качестве подмассива, и метод назначения выглядит следующим образом:
let length = this.data.list.length;
this.setData({
[`list[${length}]`]: newList
});
При этом шаблон тоже нужно соответственно изменить на двойной шлейф:
<block wx:for="{{list}}" wx:for-item="listItem" wx:key="{{listItem}}">
<child wx:for="{{listItem}}" wx:key="{{item}}"></child>
</block>
Потяните вниз, чтобы загрузить, давайте вернемся до освобождения на ночь
Для продуктов с информационными потоками загрузка с раскрывающимся списком неизбежна.
Данные, загруженные раскрывающимся списком, необходимо вставить вверху списка, поэтому мы должны сделать это:
this.setData({
`list[-1]`: newList
})
О нет, извините, это неправильно, это должно выглядеть так:
this.setData({
list: this.data.list.unshift(newList)
});
Это хорошо, это модифицировать весь массив за один раз, и за ночь вернуться к пре-релизу...
Чтобы решить эту проблему, вот небольшая хитрость:
- Поддерживать отдельный двумерный массив pullDownList для выпадающей загрузки
- При рендеринге используйте wxs для реверса pullDownList
На данный момент, когда раскрывающийся список загружен, вы можете изменить только определенный подэлемент массива:
let length = this.data.pullDownList.length;
this.setData({
[`pullDownList[${length}]`]: newList
});
Ключ при рендерингеобратный рендеринг:
<wxs module="utils">
function reverseArr(arr) {
return arr.reverse()
}
module.exports = {
reverseArr: reverseArr
}
</wxs>
<block wx:for="{{utils.reverseArr(pullDownList)}}" wx:for-item="listItem" wx:key="{{listItem}}">
<child wx:for="{{listItem}}" wx:key="{{item}}"></child>
</block>
задача решена!
использованная литература
- Прощай, мини-программы WeChat с точки зрения Ultimate Snake Skin God’s Perspective setData, Fake True Fool, 12 августа 2018 г.