过渡组件组

<TransitionGroup>
Introduction
. 内置组件 - 无需注册即可在任意别的组件中使用
. 为列表中的 多个 元素或组件提供过渡效果
. 一个 v-for 列表中的元素或组件被插入,移动|顺序改变,或移除时应用动画
. 不需要使用条件来决定渲染过渡
. 默认情况下,它不会渲染一个容器元素。但你可以通过传入 tag 属性来指定一个元素作为容器元素来渲染
. 列表中的每个元素都必须有一个独一无二的 key - <TransitionGroup> children must be keyed.
. 和 <Transition> 的使用方法- 基本一致
. 多用于应用管理场景:用户管理、留言管理、商品管理、代办事项等等
. 更多信息,请访问 官方文档 - transition-group官方文档 - API
<TransitionGroup tag="ul" move-class="your-class">
  <li v-for="(item, ind) in lists" :key="item.id">
   // ...
  </li>
</TransitionGroup>
属性 Props
name?

. 同 <Transition>

tag?: string

. 如果未定义,则渲染为片段 fragment

. 建议使用,可以节省一个 DOM 节点,如声明为 tag = "ul"

moveClass?: string

. 用于自定义过渡期间被应用的 CSS,用于覆盖默认的 .v-move 类,从而实现自定义的移动过渡效果

. 在模板中使用 kebab-case,例如 move-class = "xxx"

v-move
. 新内置类
. 对移动中的元素应用的过渡
. 当列表中的元素因为重新排序而需要改变位置时,这个类会被应用到正在移动的元素上
. 可以使用属性 moveClass 定制
如果使用了位移 transform,可能导致出现水平滚动条,请为容器指定 overflow-x: hidden
封装 Encapsulation
. 同一个项目中,过渡效果应尽量保持一致,不要太多
[] 封装过渡组件 FadeTransition.vue
. 指定过渡样式;无法在组件内直接指定,应在 全局样式 中指定;为什么?
<div class="fade-transition">
  <TransitionGroup tag="ul" name="fade-list">
    <slot></slot>
  </TransitionGroup>
</div>
Drill
[] 加载数据,渲染时增加过渡效果
逻辑

. 加载积分榜数据;数据清洗后,选择积分大于10的数据项

const lists = ref([])
onMounted(() => {
  fetch('https://glpla.github.io/utils/data/rank/20240203.json')
    .then(res => res.json())
    .then(data => {
      lists.value = data.cont.filter(item => item.ucredit > 10)
    })
})
结构

. 指定渲染标签 tag 为 ul

. 以内联变量 style 的形式,根据迭代变量 ind 分配不同的延时时间

. 可以在结构中处理延时时间,也可以在样式中处理延时时间;这里在结构中处理

多个元素使用延迟触发,用户体验更强烈;文档使用自定义属性 data- 实现;建议使用内联变量更方便

<TransitionGroup tag="ul">
  <li class="item" v-for="(item, ind) in lists" :key="item.id" :style="`--delay:${ind * 0.1}s`">
    <span>{{ item.usn }}</span>
    <span>{{ item.uname }}</span>
    <span>{{ item.ucredit }}</span>
  </li>
</TransitionGroup>
样式

. 从右上角移入;使用延时

. 其它样式略

. 为上级元素指定移除隐藏,可以消除元素位移导致触发滚动条

.v-enter-active,
.v-leave-active {
  transition: all 0.5s var(--delay) ease-in-out;
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
  transform: translateY(-30px) translateX(30px);
}
增加数据

. 增加一个元素,分配添加数据项的方法(头插/尾插/任意位置插入),查看数据的过渡效果;方法自行实现

<div @click="addItem">add</div>
解决方案

. 使用 v-move 改善过渡效果;完善样式如下

.v-move,
.v-enter-active,
.v-leave-active {
  transition: all 0.5s var(--delay) ease-in-out;
}

.v-enter-from,
.v-leave-to {
  opacity: 0;
  transform: translateY(-30px) translateX(30px);
}
删除数据

. 增加一个元素,分配删除数据项的方法(头部删除/尾部删除/任意位置删除),查看数据的过渡效果;方法自行实现

<div @click="delItem">deleete</div>
解决方案

. 过渡时,脱离文档流;增加一个样式如下

.v-leave-active {
  position: absolute;
}
封装为组件,再次实现案例
Summary
<TransitionGroup>的基本使用
新属性 tag
新类 v-move
Homework
[] 代办事项
. 列表渲染事项数据
. 每条数据可以在完成时删除
. 删除时,要显示确认对话框 - 应用过渡
. 单击可以增加一条新的事项数据 - 应用过渡
1. 结构
<div class = "msg">
    <h3>待办事项</h3>
    <div class="ipt-box">
        <input type="text" required v-model="todo" @keydown.enter="insertItem">
        <button @click="insertItem">增加</button>
    </div>
    <template v-if="arr.length">
        <div class="item">
            <p>序号</p>
            <p>待办事项</p>
            <p>操作</p>
        </div>
        <TransitionGroup name="list" tag="ul">
            <li class="item" v-for="(item, ind) in arr" :key="item.id" :style="`--delay: ${ind}`">
                <p>{{ ind }}</p>
                <p>{{ item }}</p>
                <button class="del-btn" @click="deleteItem(ind)">删除</button>
            </li>
        </TransitionGroup>
    </template>
    <template v-else>暂无记录</template>
</div>
2. 样式
. 内联变量 --delay:依次延时触发
. v-move:对移动中的元素应用的过渡,专用 于<TransitionGroup>
. v-leave-active:声明为绝对定位,保证删除不会跳跃
.v-move,
.v-enter-active,
.v-leave-active {
    transition: 0.4s ease-in-out calc(var(--delay)*0.1s);
}

.v-leave-active {
    position: absolute;
}

.v-enter-from,
.v-leave-to {
    opacity: 0;
    transform: translateX(30px);
}