Vue CLI $nextTick 过渡与动画

$nextTick

这是一个生命周期钩子 this.$nextTick(回调函数)在下一次DOM更新结束后执行其指定的回调 什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行

过渡和动画

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

image-20230630152442457

写法

  1. 准备好样式

    ○元素进入的样式

    ​ ⅰv-enter 进入的起点

    ​ ⅱv-enter-active 进入过程中

    ​ ⅲv-enter-to 进入的终点

    ○ 元素离开的样式

    ​ ⅰv-leave 离开的起点

    ​ ⅱv-leave-active 离开过程中

    ​ ⅲv-leave-to 离开的终点

  2. 使用<transition>包裹要过度的元素,并配置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>
  1. 备注:若有多个元素需要过度,则需要使用,且每个元素都要指定key值

    <transition-group name="hello" appear>
      <h1 v-show="!isShow" key="1">你好啊!</h1>
      <h1 v-show="isShow" key="2">尚硅谷!</h1>
    </transition-group>
    
  2. 第三方动画库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>
    

    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>
    

    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>
    

    test2.vue

    <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:'Test',
        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>
    

    插槽

    默认插槽

    App.vue

    <template>
      <div class="container">
        <Category title="美食">
          <img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
        </Category>
    
        <Category title="游戏">
          <ul>
            <li v-for="(g,index) in games" :key="index">{{ g }}</li>
          </ul>
        </Category>
    
        <Category title="电影">
          <video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
        </Category>
      </div>
    </template>
    
    <script>
    import Category from './components/Category.vue'
    
    export default {
      name: 'App',
      components: {
        Category
      },
      data() {
        return {
          foods: ['火锅', '烧烤', '小龙虾', '牛排'],
          games: ['红色警戒', '穿越火线', '劲舞团', '超级玛丽'],
          films: ['《教父》', '《拆弹专家》', '《你好,李焕英》', '《尚硅谷》']
        }
      },
    }
    </script>
    
    <style scoped>.container {
      display: flex;
      justify-content: space-around;
    }</style> 
    
    

    Category.vue

    <template>
    <div class="category">
      <h3>{{title}}分类</h3>
      <!--定义一个插槽,等待组件使用者填充-->
      <slot>我是一些默认值,当使用者没有传递</slot>
    </div>
    </template>
    
    <script>
    export default {
      name: 'Category',
      props:['title'],
      data() {
        return {}
      },
      methods: {},
    }
    </script>
    
    <style scoped>
      .category{
        background-color: skyblue;
        width: 200px;
        height: 300px;
      }
      h3 {
        text-align: center;
        background-color: orange;
      }
      video {
        width: 100%;
      }
      img {
        width: 100%;
      }
    </style>
    

    具名插槽

    App.vue

    <template>
    	<div class="container">
    		<Category title="美食" >
    			<img slot="conter" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
    			<a slot="footer" href="http://www.atguigu.com">更多美食</a>
    		</Category>
    
    		<Category title="游戏" >
    			<ul slot="center">
    				<li v-for="(g,index) in games" :key="index">{{g}}</li>
    			</ul>
    			<div class="foot" slot="footer">
    				<a href="http://www.atguigu.com">单机游戏</a>
    				<a href="http://www.atguigu.com">网络游戏</a>
    			</div>
    		</Category>
    
    		<Category title="电影">
    			<video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
    			<template v-slot:footer>
    				<div class="foot">
    					<a href="http://www.atguigu.com">经典</a>
    					<a href="http://www.atguigu.com">热门</a>
    					<a href="http://www.atguigu.com">推荐</a>
    				</div>
    				<h4>欢迎前来观影</h4>
    			</template>
    		</Category>
    	</div>
    </template>
    
    <script>
    	import Category from './components/Category'
    	export default {
    		name:'App',
    		components:{Category},
    		data() {
    			return {
    				foods:['火锅','烧烤','小龙虾','牛排'],
    				games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
    				films:['《教父》','《拆弹专家》','《你好,李焕英》','《尚硅谷》']
    			}
    		},
    	}
    </script>
    
    <style scoped>
    	.container,.foot{display: flex;justify-content: space-around;}
    	h4{text-align: center;}
    </style>
    

    Category.vue

    <template>
    	<div class="category">
    		<h3>{{title}}分类</h3>
    		<!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
    		<slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现1</slot>
    		<slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现2</slot>
    	</div>
    </template>
    
    <script>
    	export default {
    		name:'Category',
    		props:['title']
    	}
    </script>
    
    <style scoped>
    	.category{background-color: skyblue;width: 200px;height: 300px;}
    	h3{text-align: center;background-color: orange;}
    	video{width: 100%;}
    	img{width: 100%;}
    </style>
    

    作用域插槽

    App.vue

    <template>
    	<div class="container">
    
    		<Category title="游戏">
    			<template scope="atguigu">
    				<ul>
    					<li v-for="(g,index) in atguigu.games" :key="index">{{g}}</li>
    				</ul>
    			</template>
    		</Category>
    
    		<Category title="游戏">
    			<template scope="{games}">
    				<ol>
    					<li style="color:red" v-for="(g,index) in games" :key="index">{{g}}</li>
    				</ol>
    			</template>
    		</Category>
    
    		<Category title="游戏">
    			<template slot-scope="{games}">
    				<h4 v-for="(g,index) in games" :key="index">{{g}}</h4>
    			</template>
    		</Category>
    	</div>
    </template>
    
    <script>
    	import Category from './components/Category'
    	export default {
    		name:'App',
    		components:{ Category },
    	}
    </script>
    
    <style scoped>
    	.container,.foot{display: flex;justify-content: space-around;}
    	h4{text-align: center;}
    </style>
    

    Category.vue

    <template>
    	<div class="category">
    		<h3>{{title}}分类</h3>
    		<slot :games="games" msg="hello">我是默认的一些内容</slot>
    	</div>
    </template>
    
    <script>
    	export default {
    		name:'Category',
    		props:['title'],
    		data() {
    			return {
    				games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
    			}
    		},
    	}
    </script>
    
    <style scoped>
    	.category{background-color: skyblue;width: 200px;height: 300px;}
    	h3{text-align: center;background-color: orange;}
    	video{width: 100%;}
      img{width: 100%;}
    </style>