文章目录
Element Plus中el-tabs左右滑动动画的实现
问题:使用Transition,TransitionGroup解决不了时,可以使用以下方式:
<template>
<el-tabs v-model="activeName" class="demo-tabs" @tab-click="tabClick">
<el-tab-pane label="User" name="first" :class="tabContentClass">
<A></A>
</el-tab-pane>
<el-tab-pane label="Config" name="second" :class="tabContentClass">
<B></B>
</el-tab-pane>
<el-tab-pane label="Role" name="third" :class="tabContentClass">
<C></C>
</el-tab-pane>
</el-tabs>
</template>
<script setup>
import { ref, reactive, markRaw, nextTick, computed } from 'vue'
import A from '@/views/pageTest/components/A.vue'
import B from '@/views/pageTest/components/B.vue'
import C from '@/views/pageTest/components/C.vue'
const activeName = ref('first')
const activeObj = reactive({
preIndex: 0,
curIndex: 0,
})
function tabClick(tab) {
activeObj.preIndex = Number(activeObj.curIndex)
activeObj.curIndex = Number(tab.index)
//使用nextTick并不会失效,因为切换执行速度太快,反应不及
// nextTick(() => {
// console.log('更新了...')
// activeObj.preIndex = Number(activeObj.curIndex)
// })
//小技巧:使用延迟执行函数解决,迟一点再改变值
setTimeout(() => {
activeObj.preIndex = Number(activeObj.curIndex)
}, 200)
}
const tabContentClass = computed(() => {
return {
'slide-enter-active': true,
'slide-leave-active': activeObj.curIndex > activeObj.preIndex,
'slide-enter': activeObj.curIndex < activeObj.preIndex,
'slide-leave-to': activeObj.curIndex > activeObj.preIndex,
}
})
</script>
<style scoped>
.slide-enter-active,
.slide-leave-active {
transition: all 0.5s;
}
.slide-enter {
transform: translateX(100%);
opacity: 0;
}
.slide-leave-to {
transform: translateX(-100%);
opacity: 0;
}
</style>
vue使用<TransitionGroup>对列表项使用过渡动画,效果只会作用在最后一个元素的问题
原因:v-for没有使用 :key 绑定,自然不知道对那个元素使用动画效果
解决:绑定 :key 即可
在 Vue 3 中,原生的 Vue 响应式系统并不直接支持监听 DOM 元素的宽度和高度变化,因为这些属性不是 Vue 的响应式依赖。
使用 ResizeObserver
ResizeObserver 是一个内置的浏览器 API,用于异步观察元素尺寸的变化。这是一个更现代且可靠的方法来监听元素的尺寸变化。
<template>
<el-button @click="addHeight">加高+</el-button>
<div ref="resizableElement" class="resizable">
<!-- Your content here -->
</div>
</template>
<script>
import { ref, onMounted, onUnmounted } from 'vue'
export default {
setup() {
const resizableElement = ref(null)
const handleResize = (entries) => {
for (let entry of entries) {
const { width, height } = entry.contentRect
console.log(`Element size is ${width}px wide x ${height}px tall`)
// 在这里你可以将新的宽度和高度设置为 Vue 的响应式数据
}
}
// 创建一个 ResizeObserver 实例
const resizeObserver = new ResizeObserver(handleResize)
onMounted(() => {
if (resizableElement.value) {
resizeObserver.observe(resizableElement.value)
}
})
onUnmounted(() => {
if (resizableElement.value) {
resizeObserver.unobserve(resizableElement.value)
}
})
let cur = 0
const addHeight = () => {
cur += 10
resizableElement.value.style.height = 100 + cur + 'px'
resizableElement.value.style.width = 100 + cur + 'px'
}
return {
resizableElement,
addHeight,
}
},
}
</script>
<style scoped>
.resizable {
width: 100px;
height: 100px;
border: 1px solid black;
}
</style>