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:
@@ -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>;
|
||||
|
Reference in New Issue
Block a user