Vue3(撩课学院)笔记03-slot插糟,具名插槽,渲染作用域,作用域插槽,动态组件、异步组件、生命周期、watch侦听器、组件单向数据流、props动态绑定传参,no-props,过渡及动画

1、插槽的具体定义及基本使用
 - 插槽就是子组件提供给父组件使用的一个占位符,用<slot></slot>表示
 - 父组件可以在这个占位符中填充任何模板代码,如html,组件等
 - 填充的内容会替换子组件<slot></slot>标签

案例

<body>
<div id="app">
  <sub-Box>
  <!-- 组件标签对内的内容是用来填充slot插槽的-->
    <button>我需要一个按钮</button>
  </sub-Box>
  <sub-Box> </sub-Box>
  <sub-Box>
    <input type="text" placeholder="please input words"/>
  </sub-Box>
</div>
<!--把模板标签化了-->
<template id="sub">
  <div style="width: 200px; height: 160px ; border:1px solid gray">
    <h4>这是一个子组件</h4>
    <p>这里是一些文字内容</p>
    <!--预留一个插槽,注意插槽是放在template里面哦-->
    <slot>我可以有一个默认内容</slot>

  </div>

</template>
<!--把模板标签化了-->

<script>
  //1、创建一个子组件
const subBox={
  data(){
    return {

    }
  },
  template:'#sub'
}
  //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
      msg:'这是根组件的默认信息'
     }
   },
   components:{
     'subBox':subBox
   }
 })

app.mount('#app')

</script>
</body>
2、具名插槽
  • 解决有多个插槽时,父组件的内容如何对应子组件的哪一个slot标签
  • 如果每个插槽都有名字,那么父组件的内容就可以对号入座了
  • 插槽通过name赋予插槽名字
  • 父组件通过template及v-slot:name来对号入座
<body>
<div id="app">
  <sub-com>
    <!-- v-slot:name 去和具名的插槽一一对应,对号入座  -->
    <template v-slot:headd>我把自己塞进了头部slot里面</template>
    <template v-slot:boddy>我把自己塞进了身体slot里面</template>
    <template v-slot:foott>我把自己塞进了脚部slot里面</template>
  </sub-com>
</div>
<!--把模板标签化了-->
<template id="sub">
  <h3>这是我的子组件</h3>
  <div id="headd">
    <!--  通过name给插槽具名  -->
    <slot name="headd"></slot>
  </div>
  <div id="bodyy">
    <slot name="boddy"></slot>
  </div>
  <div id="foott">
    <slot name="foott"></slot>
  </div>

</template>

<script>
  //1、创建一个子组件
const sub={
  data(){
    return {

    }
  },
  template:'#sub'
}
  //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
      msg:'这是根组件的默认信息'
     }
   },
   components:{
      'sub-com':sub
   }
 })

app.mount('#app')

</script>
</body>
3、渲染作用域
  • 父级模板里的所有内容都是在父级作用域中编译的,也就是访问不到子组件的data数据
  • 子模板的所有内容都是在子作用域中编译的,也就是访问不到子组件的data数据
<body>
<div id="app">
   <!--  父级作用域读取父级组件的data数据-->
    <subcom v-show="isShow"></subcom>
</div>
<!--把模板标签化了-->
<template id="sub">
  <!--  子级作用域读取子级组件的data数据-->
  <div style="width: 200px; height: 100px; background-color: red">
    <h3>我是一个子组件</h3>
    <button  v-show="isShow" >我是一个按钮</button>
  </div>
</template>
<script>
  //1、创建一个子组件
const sub={
  data(){
    return {
      // 只能控制子组件内部元素的显示与否
      isShow: false
    }
  },
  template:'#sub'
}
  //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
       // 只能控制父组件元素的显示与否
       isShow:true,
       msg:'这是根组件的默认信息'
     }
   },
   components:{
      'subcom':sub
   }
 })

app.mount('#app')

</script>
</body>
4、作用域插槽
  • 父组件替换插槽中的标签
  • 但使用的是子组件中的数据(一般来说父组件不使用子组件的数据,但作用域插槽是使用子组件数据替换子组件插槽的内容)
  • 说白了就是用子组件的数据在父组件内插入子组件(有没有多此一举的感觉)
<body>
<div id="app">
  <subcom></subcom>
  <p>---------</p>
  <subcom>
    <template v-slot:default></template>
  </subcom>
  <p>---------</p>
  <subcom>
    <!--接收从子组件模板传来的数据    -->
    <template v-slot:default="slotProps">//由于子组件插槽没有具名,所以使用default,再在default后面使用slotProps接受从子组件:data传来的nameArray
      <span>{{slotProps.data.join('--')}}</span>
    </template>
  </subcom>
</div>
<!--把模板标签化了-->
<template id="sub">
  <div style="width: 200px; height: 300px; background-color: red">
    <h3>我是一个子组件</h3>
    <!--  这里绑定data数据,方便父组件调用-->
    <slot :data="nameArray">
      <ul>
        <li v-for="item in nameArray">{{item}}</li>
      </ul>
    </slot>
  </div>

</template>
<script>
  //1、创建一个子组件
  const sub={
    data(){
      return {
        nameArray:['zhangsan','lisi','wangwu','zhaoliu']
      }
    },
    template:'#sub'
  }

  //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
       // 只能控制父组件元素的显示与否

       msg:'这是根组件的默认信息'
     }
   },
   components:{
     'subcom':sub
   }
 })

app.mount('#app')

</script>
</body>
5、动态组件
  • 当组件之间切换的时候,有时回想保持这些组件的状态,以避免反复重渲染导致的性能问题
  • 根据数据的变化,结合component标签,来动态切换组件的显示代码

实际就是动态调整组件名称

一个传统的(非动态组件)切换组件显示转态代码

<body>
<div id="app">

</div>

<script>


  //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
       showItem:'mybutton'
     }
   },
   methods:{
     changeHandler(){
       if (this.showItem ==='mybutton'){
         this.showItem= 'myinput'
       }else{
         this.showItem= 'mybutton'
       }
     }

   },
   template:`
    <mybutton v-show="showItem==='mybutton'"></mybutton>
    <br/>
    <myinput  v-show="showItem==='myinput'"></myinput>

    <p>-----</p>
    <button @click="changeHandler">切换</button>
   `

 })
  //1、创建一个子组件
  app.component('mybutton',{
    data(){
      return {

      }
    },
    template:`<button>按钮全局组件</button>`
  })

  app.component('myinput',{
    data(){
      return {

      }
    },
    template:`<input type="text" placeholder="请输入一些东西"/>`
  })
app.mount('#app')

</script>
</body>

使用动态组件:is=‘动态变量’来实现组件的动态呈现
实际上就是让component的名称动态来改变

<body>
<div id="app">

</div>

<script>


  //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
     //这里的开关变量的值是组件的名称
       showItem:'mybutton' //还可以是myinput
     }
   },
   methods:{
     changeHandler(){
       if (this.showItem ==='mybutton'){
         this.showItem= 'myinput'
       }else{
         this.showItem= 'mybutton'
       }
     }

   },
   template:`
    这里使用:is="数据名"来完成动态显示的效果,对于失活组件用keep-alive来缓存之前输入的数据<br/>
    <keep-alive>
      <component :is="showItem"></component>
    </keep-alive>
    <p>-----</p>
    <button @click="changeHandler">切换</button>
   `

 })
  //1、创建一个子组件
  app.component('mybutton',{
    data(){
      return {

      }
    },
    template:`<button>按钮全局组件</button>`
  })

  app.component('myinput',{
    data(){
      return {

      }
    },
    template:`<input type="text" placeholder="请输入一些东西"/>`
  })
app.mount('#app')

</script>
</body>
6、异步组件
  • 在大型应用中,我们可能需要将应用分割成一些小的代码块,并且只在需要的时候才从服务器加载模块
  • Vue中通过defineAsynccomponent(定义异步组件)的方法实现异步组件
  • defineAsynccomponent通过异步函数来返回一个Promise对象
  • 需在Promise的resolve对象中返回响应的组件模板
<body>
<div id="app">
  <async-item></async-item>
</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
     }
   },

 })
 //使用vue点出异步组件
 app.component('async-item',Vue.defineAsyncComponent(()=>{
   return new Promise((resolve,reject)=>{
      setTimeout(()=>{
        resolve({
          template:`<div>服务器端请求来的异步组件</div>`
        })

      },3000)
   })
 }))

app.mount('#app')

</script>
</body>
7、组件生命周期

各类钩子函数

<body>
<div id="app">

</div>

<script>
 //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
       count:0
     }
   },
   methods:{
     modifydata(){
       this.count++
     }
   },
   //组件实例生成之前执行
   beforeCreate(){
     console.log('beforeCreate excuted')
   },
   //组件实例生成之后执行
   created(){
     console.log('Create excuted')
   },
   //组件实例调用之前执行
   beforeMount () {
     console.log('before component mounted')
   },
   //组件实例调用之后执行
   mounted(){
     console.log('mounted')
   },
   //数据发生变化时会执行,注意数据已经变了
   beforeUpdate(){
     console.log(this.count)
     console.log('datas is before upgrade')
   },
   //数据发生变化时,页面dom也更新完毕后会执行
   updated(){
     console.log(this.count)
     console.log('datas is  upgraded')
   },
    //实例失效时
   beforeUnmount () {
     console.log('component is  beforeunmounted')
   },
   //实例失效后,dom也被销毁
   unmount () {
     console.log('component is  unmounted')
   },

   template:`<h3>here is root element {{count}}</h3><br/><button @click="modifydata">修改数据</button>`

 })

app.mount('#app')

</script>
</body>
8、watch侦听器
  • watch侦听器是计算属性computed的底层实现
  • computed和watch都能实现的功能,建议使用computed,因为其更简洁
  • watch不用再页面渲染,计算属性需要渲染
  • 计算属性默认深度依赖,watch默认浅度观测
  • 计算属性适合做筛选,不可异步,watch适合做执行异步或开销较大的操作
<body>
<div id="app">
  <h3>normal price:{{price}}</h3>
  <h3>vip price:{{memberprice}}</h3>
  <button @click="chagnePrice">change price</button>
</div>

<script>
 //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
       price:19
     }
   },
   methods:{
     chagnePrice(){
       this.price++
     }
   },
   computed:{
     memberprice(){
       return this.price*0.8
     }
   },
   //监听data里面所有数据的改变
   watch:{
   	//可以做异步处理
    price(current,prev){
       setTimeout(()=>{
         console.log('price is changing')
         console.log(current)
         console.log(prev)
         this.memberprice=this.price*0.8
       },2000)

     },
   }

 })

app.mount('#app')

</script>
</body>
9、组件的单向数据流
  • 子组件使用父组件的时候应该是单向数据流
  • 如果多个组件同时修改父组件的值,有可能是危险的。
10、父子组件props传值的动态绑定传参
<body>
<div id="app">
<subcom></subcom>

</div>

<script>
  //创建一个子组件
  const sub={
    data(){
      return {
        mytotal:this.total
      }
    },
    props: ['number1','number2','number3','number4'],
    template:`<h3>我是一个子组件</h3>
      <div>数据1:{{number1}}</div>
      <div>数据2:{{number2}}</div>
      <div>数据3:{{number3}}</div>
      <div>数据4:{{number4}}</div>
    `
  }


 //这里是根组件
 const app=Vue.createApp({
   data(){
     return {
       a:100,
       b:200,
       c:300,
       d:400,
       numberObj:{
         number1:100 ,
         number2:200 ,
         number3:300 ,
         number4:400 ,
       }
     }
   },
   methods:{

   },
   components:{
     'subcom':sub
   },
   computed:{

   },
   //监听data里面所有数据的改变
   watch:{

   },
   template: `<subcom :number1="a"  :number2="b"  :number3="c"  :number4="d" ></subcom>
    <p>-----</p>
    <subcom v-bind="numberObj"></subcom>
  `

 })

app.mount('#app')

</script>
</body>
11、no-props父组件向子组件传递标签属性
  • no-props就是不通过绑定的方式,而是直接对props的内容进行赋值,这样依然可以把父组件的内容传递给子组件
  • 主要是把父组件的属性传递给组件,而不仅仅满足与数据的传递
  • 父组件传递给子组件的属性通过$attrs来获取,并通过
    $attrs.具体属性名来指定子组件获取父组件传递来的哪一个属性。当然也可以不点具体的属性名,直接通过 $attrs获得所有属性
  • 如果不想接受父组件传递来的no-props信息,则在子组件上设置inheritAttrs:false,
  • 如果有多个同级别标签,no-props是不生效的
<body>
<div id="app">

</div>

<script>
 //创建一个子组件
 const sub={
   data(){
     return {

     }
   },
   mounted(){
     console.log(this.$attrs)
   },
   props:['info','message'],
   //可以在子组件见设置不接受no-props数据,设定inheritAttrs:false
   // inheritAttrs:false,
   //如果有多个同级别标签,no-props是不生效的
   // 父组件传递给子组件的属性通过$attrs来获取,并通过 $attrs.具体属性名来指定子组件获取父组件传递来的哪一个属性。当然也可以不点具体的属性名,直接通过 $attrs获得所有属性
   template: `
    <h3>我是子组件--{{info}}</h3>
    <div :info="$attrs.info">我是子组件--{{info}}</div>
    <div :style="$attrs.style">我是子组件--{{info}}</div>
    <div v-bind="$attrs">我是子组件--{{info}}</div>
   `

 }

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       msg: 'hello world'
     }
   },
   components: {
     'subcom': sub
   },
   //父组件传递给子组件
   template:`
    <subcom info="test attrs" style="width: 200px; height: 100px; background-color: red"></subcom>
   `
 })
app.mount('#app')

</script>
</body>
12、过渡–基本形式
  • 通过trasition或animation给铁定的目标元素添加或移除特定的class
  • 过渡的相关类名
    xxx-enter/xxx-leave:指定隐藏时的样式
    xxx-enter-active:指定显示时的transition
    xxx-leave-active:指定显示时的transition

一个基本案例

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/vue3.js"></script>
  <style type="text/css">
    @keyframes shake {
      0%{
        transform: translateX(0);
      }
      50%{
        transform: translateX(50px);
      }
      100%{
        transform: translateX(0);
      }
    }
    .box{
      width:100px;
      height: 100px;
      background-color: red;
      display: flex;
      justify-content: center;
      align-items: center;
    }
    .animate{
      animation:shake 2s infinite alternate;
    }

    /* 用来动态绑定的样式类 */

  </style>
</head>

<body>
<div id="app">

</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       isAnimate:false,
       msg: 'hello world'
     }
   },
   methods:{
     startAnimation(){
        this.isAnimate=!this.isAnimate
     }
   },
   template:`
    <div>
      <div class="box" :class="{animate:isAnimate}">测试文字</div>
      <button @click="startAnimation">开始/结束</button>
    </div>
   `
 })


app.mount('#app')

</script>
</body>
13、过渡–步骤
  • 使用transition标签包裹过渡部分的模板代码
  • 设置动画基于的样式
  • 设置相应的入场和离场动画
    xxx-enter/xxx-leave:指定隐藏时的样式
    xxx-enter-active:指定显示时的transition
    xxx-leave-active:指定显示时的transition
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/vue3.js"></script>
  <style type="text/css">
  .box{
    width: 100px;
    height: 100px;
    background-color: red;
  }
  /*入场动画类*/
    .v-enter-from{
      opacity: 0;
    }
    .v-enter-active{
      transition: all 1s ease-in;
    }
    .v-enter-to{
      opacity: 1;
    }

  /*  离场动画类*/
  .v-leave-from{
    opacity: 1;
  }
  .v-leave-active{
    transition: all 1s ease-in;

  }
  .v-leave-to{
    opacity: 0;

  }
  </style>
</head>

<body>
<div id="app">

</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       msg:'测试文本',
       flag:false
     }
   },
   methods:{

   },
   //对vue模板内的动画可以使用transition标签包裹
   template:`
    <div>
      <transition>
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>
      <br/>
      <button @click="flag=!flag">显示/隐藏</button>
    </div>
   `
 })


app.mount('#app')

</script>
</body>
14、过渡–使用自定义动画实现
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/vue3.js"></script>
  <style type="text/css">
  .box{
    width: 100px;
    height: 100px;
    background-color: red;
  }
  /*通过自定义动画实现*/
  @keyframes shake-from {
    0% {
      opacity: 0;
      transform: translateX(0);
    }
    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 1;
      transform: translateX(0);
    }
  }

  @keyframes shake-to {
    0% {
      opacity: 1;
      transform: translateX(0);
    }

    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 0;
      transform: translateX(0);
    }

  }

  /*入场动画类*/

    .v-enter-active{
      animation: 2s shake-from;
    }

  /*  离场动画类*/

  .v-leave-active{
    animation: 2s shake-to;

  }

  </style>
</head>

<body>
<div id="app">

</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       msg:'测试文本',
       flag:false
     }
   },
   methods:{

   },
   //对vue模板内的动画可以使用transition标签包裹
   template:`
    <div>
      <transition>
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>
      <br/>
      <button @click="flag=!flag">显示/隐藏</button>
    </div>
   `
 })


app.mount('#app')

</script>
</body>
  • 可以指定那些模板内容使用动画,那些不用。
  • 方法是通过在transition标签上添加name属性
  • 并在样式中以该name作为样式开头即.mytest-enter-active之类
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/vue3.js"></script>
  <style type="text/css">
  .box{
    width: 100px;
    height: 100px;
    background-color: red;
  }
  /*通过自定义动画实现*/
  @keyframes shake-from {
    0% {
      opacity: 0;
      transform: translateX(0);
    }
    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 1;
      transform: translateX(0);
    }
  }

  @keyframes shake-to {
    0% {
      opacity: 1;
      transform: translateX(0);
    }

    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 0;
      transform: translateX(0);
    }

  }

  /*入场动画类*/

    .mytest-enter-active{
      animation: 2s shake-from;
    }

  /*  离场动画类*/

  .mytest-leave-active{
    animation: 2s shake-to;

  }

  </style>
</head>

<body>
<div id="app">

</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       msg:'测试文本',
       flag:false
     }
   },
   methods:{

   },
   //对vue模板内的动画可以使用transition标签包裹
   template:`
    <div>
      <transition name="mytest">
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>
      <transition >
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>
      <transition >
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>
      <br/>
      <button @click="flag=!flag">显示/隐藏</button>
    </div>
   `
 })


app.mount('#app')

</script>
</body>
15、同时使用过渡和动画
  • 尽量让transition的市场和animation的时长一致
  • 如果时长实在不一致,可以设置模板中transition标签的type值,如果值为transition则以transition为主,值为animation则以animation为主
  • 在一个v-enter-from/to里面同时写过渡语句和自定义动画语句,如
.v-enter-active {
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-from;
    }

    .v-leave-active{
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-to;
    }

案例如:

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/vue3.js"></script>
  <style type="text/css">
  .box{
    width: 100px;
    height: 100px;
    background-color: red;
  }
  /*通过自定义动画实现*/
  @keyframes shake-from {
    0% {
      opacity: 0;
      transform: translateX(0);
    }
    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 1;
      transform: translateX(0);
    }
  }

  @keyframes shake-to {
    0% {
      opacity: 1;
      transform: translateX(0);
    }

    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 0;
      transform: translateX(0);
    }

  }

  /*入场动画类*/
    .v-enter-from{
      opacity: 0;
    }
    .v-enter-active {
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-from;
    }

    .v-leave-active{
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-to;
    }

  /*  离场动画类*/
  .v-enter-to{
    opacity: 1;

  }
  .v-leave-to{
    opacity: 0;


  }

  </style>
</head>

<body>
<div id="app">

</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       msg:'测试文本',
       flag:false
     }
   },
   methods:{

   },
   //对vue模板内的动画可以使用transition标签包裹
   template:`
    <div>
      <transition type="animation">
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>

      <br/>
      <button @click="flag=!flag">显示/隐藏</button>
    </div>
   `
 })


app.mount('#app')

</script>
</body>
  • 也可以强制使用时间。方法是在模板的transition标签上使用:duration=时间,主要要有冒号,时间单位为毫秒
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/vue3.js"></script>
  <style type="text/css">
  .box{
    width: 100px;
    height: 100px;
    background-color: red;
  }
  /*通过自定义动画实现*/
  @keyframes shake-from {
    0% {
      opacity: 0;
      transform: translateX(0);
    }
    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 1;
      transform: translateX(0);
    }
  }

  @keyframes shake-to {
    0% {
      opacity: 1;
      transform: translateX(0);
    }

    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 0;
      transform: translateX(0);
    }

  }

  /*入场动画类*/
    .v-enter-from{
      opacity: 0;
    }
    .v-enter-active {
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-from;
    }

    .v-leave-active{
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-to;
    }

  /*  离场动画类*/
  .v-enter-to{
    opacity: 1;

  }
  .v-leave-to{
    opacity: 0;


  }

  </style>
</head>

<body>
<div id="app">

</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       msg:'测试文本',
       flag:false
     }
   },
   methods:{

   },
   //对vue模板内的动画可以使用transition标签包裹
   template:`
    <div>
      <transition :duration="2000">
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>

      <br/>
      <button @click="flag=!flag">显示/隐藏</button>
    </div>
   `
 })


app.mount('#app')

</script>
</body>
  • 还可以设置进入和离开的时间,方式是:duration={enter:3000,leave:1000}
<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <script src="js/vue3.js"></script>
  <style type="text/css">
  .box{
    width: 100px;
    height: 100px;
    background-color: red;
  }
  /*通过自定义动画实现*/
  @keyframes shake-from {
    0% {
      opacity: 0;
      transform: translateX(0);
    }
    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 1;
      transform: translateX(0);
    }
  }

  @keyframes shake-to {
    0% {
      opacity: 1;
      transform: translateX(0);
    }

    50% {
      opacity: 0;
      transform: translateX(50px);
    }
    100% {
      opacity: 0;
      transform: translateX(0);
    }

  }

  /*入场动画类*/
    .v-enter-from{
      opacity: 0;
    }
    .v-enter-active {
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-from;
    }

    .v-leave-active{
      /*过渡*/
      transition: all 1s ease-in;
      /*  动画*/
      animation: 2s shake-to;
    }

  /*  离场动画类*/
  .v-enter-to{
    opacity: 1;

  }
  .v-leave-to{
    opacity: 0;


  }

  </style>
</head>

<body>
<div id="app">

</div>

<script>

 //这里是根组件
 const app=Vue.createApp({
   data () {
     return {
       msg:'测试文本',
       flag:false
     }
   },
   methods:{

   },
   //对vue模板内的动画可以使用transition标签包裹
   template:`
    <div>
      <transition :duration="{enter:3000,leave:100}">
      <div class="box" v-show="flag">{{msg}}</div>
      </transition>

      <br/>
      <button @click="flag=!flag">显示/隐藏</button>
    </div>
   `
 })


app.mount('#app')

</script>
</body>
16、animation.css第三方动画库

animate.css网站

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue3.0来了,你还学的动吗? 2020年9月底,Vue3.0正式版终于发布了。Vue在全球拥有 130 多万用户 ,它被应用于各种不同的场景中。而在国内,更是最火热的前端框架,2.0与3.0的开发模式有了很大的改变,所以3.0的全新版本势必会引发新的一波学习潮流。对于前端开发者来说,不管你嘴上如何“学不动”,注定离不开“真相定律”,Vue3.0是你提升自身技术能力,晋升中级工程师一定要掌握的。  本课程将基于 Vue3.0 正式版,从Vue基础语法入手,全面掌握 Vue3.0 全家桶技术栈,并结合实战项目开发,让你拥有Vue3.0项目开发经验,更好的掌握Vue开发企业项目的流程 。 本课程共包括三个模块 一、Vue基础篇 本模块将讲解Vue3.0基本用法、插值表达式、常用指令等知识点,还会精讲Vue 3.0核心语法,如计算属性、过滤器、监视器、模板、生命周期等内容。会带你深入理解Vue组件化技术,讲解全局组件和局部组件的定义,组件间数据传递,以及Vue内置组件等知识点。让你掌握模块化的概念,会通过Vue脚本架搭建项目,并掌握使用Axios发送AJAX请求,让你快速入门Vue3.0。 二、Vue核心篇 这个模块会带你讲解Vue3.0全家桶的知识点(Vue Router路由+Vuex状态管理),涉及Vue路由的用法、包括路由嵌套、路由模式、编程式导航、路由守卫等,还会全面讲解Vuex状态管理机制及使用,理解state、mutation、action等核心概念,让你轻松掌握Vue全家桶。 三、项目实战篇 实战项目会贴近企业流程,按照企业级别代码质量和工程开发流程进行授课,让你理解这套技术在企业中被使用的真实流程,更好的掌握Vue各个基础知识点。项目开发流程包括项目需求分析->环境搭建与配置->搭建远程Git仓库->接口分析->项目开发->打包上线。实战项目涉及内容

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值