簡單分析說下爲啥卡頓(具體查看參考文章):vue
具體查看參考文章node
不經過 props 傳遞,而是經過函數傳遞。ios
// 父組件
<huge-tree ref="huge-tree"></huge-tree>
axios.get(`/static/json/${count}.json`).then(({ data }) => {
// 注意:這裏的 data 也不要被依賴收集了,會致使卡頓。
this.$refs['huge-tree'].setData(data);
});
// 子組件
<script>
class BigData {
_data = []; // 海量數據 tree
list = []; // 扁平化的tree
filterList = []; // 根據關鍵詞過濾後的list
listMap = {}; // this.big.list 對應的 map, 便於快速找到節點。
filterTree = []; // 根據關鍵詞過濾後的tree
}
export default {
data() {
this.big = null;
return {
count: 1, // 用於視圖更新, 因爲沒有依賴收集,經過count 手動更新computed。
keyword: '', // 關鍵詞
isSearching: false, // 搜索中
itemHeigth: 27, // 每一項的高度
startIndex: 0, // 渲染的開始區間
endIndex: 70, // 渲染的結束區間
throttleSrcoll: '', // 節流
debounceInput: '',
isOnlyInCheckedSearch: false,
};
},
computed: {
// 過濾掉 hidden 節點
unHiddenList() {
return this.count ? this.big.filterList.filter(i => !i.isHidden) : [];
},
// 虛擬高度,與隱藏的數量有關
phantomHeight() {
return this.unHiddenList.length * this.itemHeigth;
},
renderList() {
return this.unHiddenList.slice(this.startIndex, this.endIndex);
},
},
created() {
this.big = new BigData();
// 滾動時的節流
this.throttleSrcoll = throttle(this.setRenderRange, 80);
// 輸入過濾條件的防抖
this.debounceInput = debounce(this.init, 300);
},
methods: {
setData(data) {
this.big._data = data;
this.init('init');
},
//init: 1. 拉平tree,2. 組織list,3. 過濾,4. 展開,5. 選中, 6. 回到頂部
init(op) {
// op: init, restore, showCheckedOnly
if (this.big._data.length === 0) return;
if (op === 'init') {
this.flatTree(this.big._data);
this.big.list.forEach(node => (this.big.listMap[node.id] = node));
}
this.initFilter(op);
if (op === 'init' || op === 'restore') this.initExpand();
this.setCheckedKeys(this.big.checkedKeys);
this.backToTop();
},
//......
}
}
</script>
複製代碼
zhuanlan.zhihu.com/p/55528376git
源碼github