fix: v-sizeディレクティブの動作を修正 (#8249)

* Fix size directive behavior not activated

* calc

* wip

* cache computed classes

* fix Vue3では使えなくなった

* 不要なIntersection Observerを削除

* comment
This commit is contained in:
tamaina
2022-02-06 10:59:36 +09:00
committed by GitHub
parent 58fa54a9a6
commit 6cbd66b534
2 changed files with 137 additions and 77 deletions

View File

@@ -1,34 +1,55 @@
import { Directive } from 'vue';
const mountings = new Map<Element, {
resize: ResizeObserver;
intersection?: IntersectionObserver;
fn: (w: number, h: number) => void;
}>();
function calc(src: Element) {
const info = mountings.get(src);
const height = src.clientHeight;
const width = src.clientWidth;
if (!info) return;
// アクティベート前などでsrcが描画されていない場合
if (!height) {
// IntersectionObserverで表示検出する
if (!info.intersection) {
info.intersection = new IntersectionObserver(entries => {
if (entries.some(entry => entry.isIntersecting)) calc(src);
});
}
info.intersection.observe(src);
return;
}
if (info.intersection) {
info.intersection.disconnect()
delete info.intersection;
};
info.fn(width, height);
};
export default {
mounted(src, binding, vn) {
const calc = () => {
const height = src.clientHeight;
const width = src.clientWidth;
// 要素が(一時的に)DOMに存在しないときは計算スキップ
if (height === 0) return;
binding.value(width, height);
};
calc();
// Vue3では使えなくなった
// 無くても大丈夫か...
// TODO: ↑大丈夫じゃなかったので解決策を探す
//vn.context.$on('hook:activated', calc);
const ro = new ResizeObserver((entries, observer) => {
calc();
const resize = new ResizeObserver((entries, observer) => {
calc(src);
});
ro.observe(src);
resize.observe(src);
src._get_size_ro_ = ro;
mountings.set(src, { resize, fn: binding.value, });
calc(src);
},
unmounted(src, binding, vn) {
binding.value(0, 0);
src._get_size_ro_.unobserve(src);
const info = mountings.get(src);
if (!info) return;
info.resize.disconnect();
if (info.intersection) info.intersection.disconnect();
mountings.delete(src);
}
} as Directive;
} as Directive<Element, (w: number, h: number) => void>;