有如下代码,使用input
时,可以正常动画,但使用<input ref="inputRef" />
时,动画效果就会出现意外,解释原因和提供解决方案
<template>
<TransitionGroup name="container" tag="ul" class="container" key="counts">
<div v-for="(_, index) in counts" :key="index">
<!-- container-leave-active container-move container-leave-to -->
<!-- container-leave-active container-leave-to -->
<!-- animation when leave doesn't work -->
<!-- <input ref="inputRef" /> -->
<!-- animation when leave works -->
<input />
<button @click="remove(index)" >delete</button>
</div>
<button @click="add" >add input</button>
</TransitionGroup>
</template>
<script>
import { ref } from 'vue'
export default {
name: 'App',
setup(){
const counts = ref([1,2,3,4,5]);
const inputRef = ref();
const add = () => {
counts.value.push(counts.value[counts.value.length - 1] + 1);
};
const remove = (index) => {
counts.value.splice(index, 1);
};
return {
inputRef,
remove,
add,
counts
}
}
}
</script>
<style>
.container {
position: relative;
display: flex;
flex-direction: column;
padding: 1rem;
row-gap: 2rem;
background: #add8e620;
}
.container-move,
.container-enter-active,
.container-leave-active {
transition: all 0.3s ease-in-out;
}
.container-enter-from,
.container-leave-to {
opacity: 0;
transform: translateX(50px);
}
.container-leave-active {
position: absolute ;
}
</style>
解决方案
并不了解具体的业务,和使用ref获取dom的场景,这里只提解决
加上序号处理
<input :ref="index+'inputRef'" />
在js中,动态的获取即可
const { proxy } = getCurrentInstance();
proxy.$refs
proxy.$refs并不是一个响应式的数据,他的内容修改后,不会全局刷新
使用父级容器,使用时,根据index处理
<TransitionGroup name="container" tag="ul" class="container" key="counts" ref="inputRef">
inputRef.querySelector("div:nth-of-type(5) button")
同样,不会产生一次渲染
原因
ref 获取dom节点的实现原理,当页面渲染后,会重新计算$refs对应的dom节点数量,此时,相当于执行了如下操作
inputRef.value = [...]
这种操作会引起第二次渲染,而第二次渲染,会对动画效果的计算产生影响,即bug