directive/transitioning.js
function getRealHeight(myDiv) {
let parentNode = myDiv.parentNode || document.body;
let content = myDiv.cloneNode(true);
content.style.height = 'auto';
content.style.visibility = 'hidden';
parentNode.appendChild(content);
let height = content.offsetHeight;
parentNode.removeChild(content);
return height;
}
const transitioningObj = {
mounted(el, binding) {
const { isTrigger } = binding.value;
const triggerFlag = computed(isTrigger);
function init() {
el.style.height = `${el.clientHeight}px`;
el.classList.add('height-transitioning');
}
nextTick(init);
const handleContentChange = () => {
nextTick(() => {
if (!el.classList.contains('height-transitioning')) {
el.classList.add('height-transitioning');
}
el.style.height = `${getRealHeight(el)}px`;
});
};
const unWatch = watch(() => triggerFlag.value, handleContentChange);
onBeforeUnmount(unWatch);
}
};
export default (app) => {
app.directive('transitioning', transitioningObj);
};
index.scss
.height-transitioning {
overflow-y: hidden;
transition: height .5s;
}
main.js
import vTransitioning from '@/directive/transitioning';
const app = createApp(App);
vTransitioning(app);
use:
<div class="itemBox" v-transitioning="{ isTrigger: () => expandIdx === index }">
</div>