Vue CLI $nextTick 过渡与动画

3.12.$nextTick

这是一个生命周期钩子

**this.$nextTick(回调函数)**在下一次DOM更新结束后执行其指定的回调

什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行

使用 $nextTick 优化 Todo-List

src/components/MyItem.vue

<template>
    <li>
       <label>
           <!-- 如下代码也能实现功能,但是不太推荐,因为有点违反原则,因为修改了props -->
           <!-- <input type="checkbox" v-model="todo.done"/> -->
           <input type="checkbox" :checked="todo.done" @change="handleCheck(todo.id)">
           <span v-show="!todo.isEdit">{{todo.title}}</span>
           <input
                   type="text"
                   v-show="todo.isEdit"
                   :value="todo.title"
                   @blur="handleBlur(todo, $event)"
                   ref="inputTitle"
           />
       </label>
        <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
        <button v-show="!todo.isEdit" class="btn btn-edit" @click="handleEdit(todo)">编辑</button>
    </li>
</template>

<script>
    import pubsub from 'pubsub-js';

    export default {
        name: "Item",
        // 声明接收todo
        props:['todo'],
        methods: {
            // 勾选or取消勾选
            handleCheck(id) {
                // 通知App组件将对应的todo对象的done值取反
                this.$bus.$emit('checkTodo',id);
            },
            // 删除
            handleDelete(id){
                if(confirm('确定删除吗?')) {
                    // 通知App组件将对应的todo对象删除
                    pubsub.publish('deleteTodo', id) // 发布消息
                }
            },
            // 编辑
            handleEdit(todo) {
                //  判断是否有isEdit属性
                if (todo.hasOwnProperty("isEdit")) {
                    todo.isEdit = true;
                } else {
                    console.log("todo身上没有isEdit")
                    this.$set(todo, "isEdit", true);
                }
                // 在下一次DOM更新借宿后执行其指定的函数
                this.$nextTick(function () {
                    this.$refs.inputTitle.focus();
                });
            },
            // 失去焦点回调(真正执行修改逻辑)
            handleBlur(todo, e) {
                todo.isEdit = false;
                if (!e.target.value.trim()) return alert("输入不能为空!");
                console.log(todo.id, e.target.value);
                this.$bus.$emit('updateTodo', todo.id, e.target.value);
            }
        }
    }
</script>

Vue CLI $nextTick 过渡与动画_第1张图片

3.13.过渡与动画

Vue封装的过度与动画:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名

Vue CLI $nextTick 过渡与动画_第2张图片

写法

  1. 准备好样式
    1. 元素进入的样式
      1. **v-enter ** 进入的起点
      2. v-enter-active 进入过程中
      3. **v-enter-to ** 进入的终点
    2. 元素离开的样式
      1. **v-leave ** 离开的起点
      2. **v-leave-active ** 离开过程中
      3. v-leave-to 离开的终点
  2. 使用包裹要过度的元素,并配置name属性,此时需要将上面样式名的v换为name
  3. 要让页面一开始就显示动画,需要添加appear
    <transition name="hello" appear> 
      <h1 v-show="isShow">你好啊!</h1>
    </transition> 
    <style> 
      .hello-enter-active { 
        animation: hello 0.5s linear; 
      }
      .hello-leave-active { 
        animation: hello 0.5s linear reverse; 
      }
      @keyframes hello { 
        from { 
          transform: translateX(-100%); 
        } 
        to { 
          transform: translateX(0px); 
        }
      }
    </style>
    
  4. 备注:若有多个元素需要过度,则需要使用,且每个元素都要指定key
    <transition-group name="hello" appear> 
      <h1 v-show="!isShow" key="1">你好啊!</h1> 
      <h1 v-show="isShow" key="2">尚硅谷!</h1> 
    </transition-group>
    
  5. 第三方动画库Animate.css
    <transition-group appear 
      name="animate__animated animate__bounce" 
      enter-active-class="animate__swing"
      leave-active-class="animate__backOutUp">
      <h1 v-show="!isShow" key="1">你好啊!</h1> 
      <h1 v-show="isShow" key="2">尚硅谷!</h1> 
    </transition-group>
    

src/App.vue

<template>
    <div> 
        <Test/>
        <Test2/>
        <Test3/>
    </div>
</template> 

<script> 
    // 引入组件
    import Test from './components/Test';
    import Test2 from './components/Test2';
    import Test3 from './components/Test3';

    export default { 
        name:'App',
        components: {
            Test,
            Test2,
            Test3
        }
    }
</script>

src/components/test.vue

<template>
    <div>
        <button @click="isShow = !isShow">显示/隐藏</button>
        <transition name="hello" appear>
            <h1 v-show="isShow">你好啊!</h1>
        </transition>
    </div>
</template>

<script>
    export default {
        name: 'Test',
        data() {
            return {
                isShow: true
            }
        }
    }
</script>

<style scoped>
    h1 {
        background-color: orange;
    }
    .hello-enter-active { 
        animation: atguigu 0.5s linear; 
    }
    .hello-leave-active { 
        animation: atguigu 0.5s linear reverse; 
    }
    @keyframes atguigu { 
        from {
            transform: translateX(-100%);
        } 
        to {
            transform: translateX(0px);
        } 
    }
</style>

src/components/test2

<template>
    <div>
        <button @click="isShow = !isShow">显示/隐藏</button>
        <transition-group name="hello" appear>
            <h1 v-show="!isShow" key="1">你好啊!</h1>
            <h1 v-show="isShow" key="2">尚硅谷!</h1>
        </transition-group>
    </div>
</template>

<script>
    export default {
        name: 'Test2',
        data() {
            return {
                isShow: true
            }
        }
    }
</script>

<style scoped>
    h1 {
        background-color: orange;
        /* transition: 0.5s linear; */
    }
    /* 进入的起点、离开的终点 */
    .hello-enter,.hello-leave-to { 
        transform: translateX(-100%);
    }
    .hello-enter-active,.hello-leave-active{ 
        transition: 0.5s linear; 
    }
    /* 进入的终点、离开的起点 */ 
    .hello-enter-to,.hello-leave { 
        transform: translateX(0); 
    }
</style>

Vue CLI $nextTick 过渡与动画_第3张图片

src/components/test3

<template>
    <div>
        <button @click="isShow = !isShow">显示/隐藏</button>
        <transition-group
                appear
                name="animate__animated animate__bounce"
                enter-active-class="animate__bounce"
                leave-active-class="animate__backOutUp"
        >
            <h1 v-show="!isShow" key="1">你好啊!</h1>
            <h1 v-show="isShow" key="2">尚硅谷!</h1>
        </transition-group>
    </div>
</template>

<script>
    import "animate.css";
    
    export default {
        name: 'Test3',
        data() {
            return {
                isShow: true
            }
        }
    }
</script>

<style scoped>
    h1 {
        background-color: orange;
        /* transition: 0.5s linear; */
    }
</style>

使用动画优化 Todo-List

src/components/MyList.vue

<template>
    <ul class="todo-main">
        <transition-group name="todo" appear>
            <MyItem v-for="todoObj in todos" :key="todoObj.id" :todo="todoObj"/>
        </transition-group>
    </ul>
</template>

<script>
    import MyItem from './MyItem';
    
    export default {
        name: "List",
        components: {
            MyItem
        },
        props:['todos']
    }
</script>

<style scoped>
    .todo-main {
        margin-left: 0px;
        border: 1px solid #ddd;
        border-radius: 2px;
        padding: 0px;
    }
    .todo-empty {
        height: 40px;
        line-height: 40px;
        border: 1px solid #ddd; 
        border-radius: 2px;
        padding-left: 5px;
        margin-top: 10px;
    }
    .todo-enter-active {
        animation: liqb 0.5s linear;
    }
    .todo-leave-active {
        animation: liqb 0.5s linear reverse;
    }
    @keyframes liqb {
        from {
            transform: translateX(-100%);
        }
        to {
            transform: translateX(0px);
        }
    }
</style>

你可能感兴趣的:(vue,vue.js,javascript,ecmascript)