Vue基础(三)

1、Vue中的动画

动画能够提高用户的体验,帮助用户更好的理解页面中的功能

使用过渡类名

在进入/离开的过渡中,会有 6 个 class 切换。

  1. v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除。

  2. v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。

  3. v-enter-to2.1.8版及以上 定义进入过渡的结束状态。在元素被插入之后下一帧生效 (与此同时 v-enter 被移除),在过渡/动画完成之后移除。

  4. v-leave: 定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。

  5. v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。

  6. v-leave-to2.1.8版及以上 定义离开过渡的结束状态。在离开过渡被触发之后下一帧生效 (与此同时 v-leave 被删除),在过渡/动画完成之后移除。

使用的时候可以分为两组搭配使用,一种是时间点,一种是时间段

v-enter 【这是一个时间点】 是进入之前,元素的起始状态,此时还没有开始进入

v-leave-to 【这是一个时间点】 是动画离开之后,离开的终止状态,此时,元素 动画已经结束了

v-enter-active 【入场动画的时间段】

v-leave-active 【离场动画的时间段】

注意:在使用动画的时候,需要通过 transition 元素,把 需要被动画控制的元素,包裹起来。对于这些在过渡中切换的类名来说,如果你使用一个没有名字的 <transition>,则 v- 是这些类名的默认前缀。如果你使用了 <transition name="my-transition">,那么 v-enter 会替换为 my-transition-enter

  <script src="./lib/vue-2.4.0.js"></script>
  <!-- 2. 自定义两组样式,来控制 transition 内部的元素实现动画 -->
  <style>
    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateX(150px);
    }
    .v-enter-active,
    .v-leave-active{
      transition: all 0.8s ease;
    }
    .my-enter,
    .my-leave-to {
      opacity: 0;
      transform: translateY(70px);
    }

    .my-enter-active,
    .my-leave-active{
      transition: all 0.8s ease;
    }
  </style>
</head>

<body>
  <div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    <transition>
      <h3 v-if="flag">这是一个H3</h3>
    </transition>
    <hr>
    <input type="button" value="toggle2" @click="flag2=!flag2">
    <transition name="my">
      <h6 v-if="flag2">这是一个H6</h6>
    </transition>
  </div>

  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false,
        flag2: false
      },
      methods: {}
    });
  </script>
</body>

</html>

使用第三方CSS动画库

  • 首先先引入第三方类animated.css
<link rel="stylesheet" type="text/css" href="./lib/animate.css">

 

  • 定义 transition 及属性
  • 在transition元素中添加enter-active-class/leave-active-class入场离场属性

但是设置的值前面必须加上animated(当然也可以不在transition上设置animated,可以在你所要进行动画的标签上设置class属性为animated)

1、<transition enter-active-class="animated bounceIn" leave-active-class="animated bounceOut"

2、<h3 v-if="flag" class="animated">这是一个H3</h3>
  • 可以加入:duration来统一设置入场和离场时候的时长
1、<transition enter-active-class="bounceIn" leave-active-class="bounceOut" :duration="200">

2、 :duration="{ enter: 200, leave: 400 }"
  <script src="./lib/vue-2.4.0.js"></script>
  <link rel="stylesheet" href="./lib/animate.css">
  <!-- 入场 bounceIn    离场 bounceOut -->
</head>
<body>
  <div id="app">
    <input type="button" value="toggle" @click="flag=!flag">
    <transition 
    enter-active-class="bounceIn" 
    leave-active-class="bounceOut" 
    :duration="{ enter: 200, leave: 400 }">
      <h3 v-if="flag" class="animated">这是一个H3</h3>
    </transition> 
  </div>
  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {}
    });
  </script>
</body>

</html>

使用动画钩子函数

  • 定义 transition 组件以及三个钩子函数 
<div id="app">
    <input type="button" value="切换动画" @click="isshow = !isshow">
    <transition
    @before-enter="beforeEnter"
    @enter="enter"
    @after-enter="afterEnter">
      <div v-if="isshow" class="show">OK</div>
    </transition>
  </div>
  • 定义三个 methods 钩子方法:

注意:动画钩子函数的第一个参数:el,表示 要执行动画的那个DOM元素,是个原生的 JS DOM对象。可以认为 , el 是通过 document.getElementById('') 方式获取到的原生JS DOM对象。

beforeEnter 表示动画入场之前,此时,动画尚未开始,可以 在 beforeEnter 中,设置元素开始动画之前的起始样式。

enter 表示动画 开始之后的样式,这里,可以设置小球完成动画之后的,结束状态。

el.offsetWidth,没有实际的作用,但是,如果不写,出不来动画效果;可以认为 el.offsetWidth 会强制动画刷新。

这里的 done, 起始就是 afterEnter 这个函数,也就是说:done 是 afterEnter 函数的引用,会使动画立即消失。

methods: {
        beforeEnter(el) { // 动画进入之前的回调
          el.style.transform = 'translateX(500px)';
        },
        enter(el, done) { // 动画进入完成时候的回调
          el.offsetWidth;
          el.style.transform = 'translateX(0px)';
          done();
        },
        afterEnter(el) { // 动画进入完成之后的回调
          this.isshow = !this.isshow;
        }
      }
  • 定义动画过渡时长和样式 
.show{
      transition: all 0.4s ease;
    }
  <script src="./lib/vue-2.4.0.js"></script>
  <style>
    .ball {
      width: 15px;
      height: 15px;
      border-radius: 50%;
      background-color: red;
    }
  </style>
</head>
<body>
  <div id="app">
    <input type="button" value="快到碗里来" @click="flag=!flag">
    <!-- 1. 使用 transition 元素把 小球包裹起来 -->
    <transition
      @before-enter="beforeEnter"
      @enter="enter"
      @after-enter="afterEnter">
      <div class="ball" v-show="flag"></div>
    </transition>
  </div>

  <script>

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {
        beforeEnter(el){
          el.style.transform = "translate(0, 0)"
        },
        enter(el, done){
          el.offsetWidth
          el.style.transform = "translate(150px, 450px)"
          el.style.transition = 'all 1s ease'
          done()
        },
        afterEnter(el){
          this.flag = !this.flag
        }
      }
    });
  </script>
</body>

</html>

v-for的列表过渡

在实现列表过渡的时候,如果需要过渡的元素,是通过 v-for 循环渲染出来的,不能使用 transition 包裹,需要使用 transitionGroup

如果要为 v-for 循环创建的元素设置动画,必须为每一个 元素 设置 :key 属性

  <script src="./lib/vue-2.4.0.js"></script>
  <style>
    li {
      border: 1px dashed #999;
      margin: 5px;
      line-height: 35px;
      padding-left: 5px;
      font-size: 12px;
      width: 100%;
    }
    li:hover {
      background-color: hotpink;
      transition: all 0.8s ease;
    }
    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateY(80px);
    }
    .v-enter-active,
    .v-leave-active {
      transition: all 0.6s ease;
    }

    /* 下面的 .v-move 和 .v-leave-active 配合使用,能够实现列表后续的元素,渐渐地漂上来的效果 */
    .v-move {
      transition: all 0.6s ease;
    }
    .v-leave-active{
      position: absolute;
    }
  </style>
</head>

<body>
  <div id="app">
    <div>
      <label>
        Id:
        <input type="text" v-model="id">
      </label>
      <label>
        Name:
        <input type="text" v-model="name">
      </label>
      <input type="button" value="添加" @click="add">
    </div>
      <transition-group appear tag="ul">
        <li v-for="(item, i) in list" :key="item.id" @click="del(i)">
          {{item.id}} --- {{item.name}}
        </li>
      </transition-group>
  </div>
  <script>
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        id: '',
        name: '',
        list: [
          { id: 1, name: '赵高' },
          { id: 2, name: '秦桧' },
          { id: 3, name: '严嵩' },
          { id: 4, name: '魏忠贤' }
        ]
      },
      methods: {
        add() {
          this.list.push({ id: this.id, name: this.name })
          this.id = this.name = ''
        },
        del(i) {
          this.list.splice(i, 1)
        }
      }
    });
  </script>
</body>

</html>

小提示:1、给 ransition-group 添加 appear 属性,实现页面刚展示出来时候,入场时候的效果

2、通过 为 transition-group 元素,设置 tag 属性,指定 transition-group 渲染为指定的元素,如果不指定 tag 属性,默认,渲染为 span 标签

3、<transition-group> 组件还有一个特殊之处。不仅可以进入和离开动画,还可以改变定位。要使用这个新功能只需了解新增的 v-move 特性,它会在元素的改变定位的过程中应用

4、v-movev-leave-active 结合使用,能够让列表的过渡更加平缓柔和

2、定义Vue组件

什么是组件: 组件的出现,就是为了拆分Vue实例的代码量的,能够让我们以不同的组件,来划分不同的功能模块,将来我们需要什么样的功能,就可以去调用对应的组件即可。

 组件化和模块化的不同:

  • 模块化: 是从代码逻辑的角度进行划分的;方便代码分层开发,保证每个功能模块的职能单一;

  • 组件化: 是从UI界面的角度进行划分的;前端的组件化,方便UI组件的重用;

全局组件定义的三种方式

  • 使用 Vue.extend 来创建全局的Vue组件
 var com1 = Vue.extend({
   template: '<h3>这是使用 Vue.extend 创建的组件</h3>' // 通过 template 属性,指定了组件要展示的HTML结构
 })
  • 使用 Vue.component('组件的名称', 创建出来的组件模板对象)

注意:1、如果使用 Vue.component 定义全局组件的时候,组件名称使用了 驼峰命名,则在引用组件的时候,需要把 大写的驼峰改为小写的字母,同时,两个单词之前,使用 - 链接。

2、如果不使用驼峰,则直接拿名称来使用即可

<script src="./lib/vue-2.4.0.js"></script>
<body>
  <div id="app">
    <!-- 如果要使用组件,直接,把组件的名称,以 HTML 标签的形式,引入到页面中,即可 -->
    <mycom1></mycom1>
  </div>

  <script>
    Vue.component('mycom1', Vue.extend({
      template: '<h3>这是使用 Vue.extend 创建的组件</h3>'
    }))
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>
</body>
</html>

简写方式:

  <script>
     var com1 = Vue.extend({
       template: '<h3>这是使用 Vue.extend 创建的组件</h3>' // 通过 template 属性,指定了组件要展示的HTML结构
     })
     Vue.component('mycom1', com1)
  </script>
  • 使用 template 元素,定义组件的HTML模板结构 (这种方式定义组件有代码提示会比较方便)
 <script src="./lib/vue-2.4.0.js"></script>
<body>
  <div id="app">
    <mycom3></mycom3>
  </div>
  <!-- 在 被控制的 #app 外面,使用 template 元素,定义组件的HTML模板结构  -->
  <template id="tmpl">
    <div>
      <h1>这是通过 template 元素,在外部定义的组件结构,这个方式,有代码的只能提示和高亮</h1>
      <h4>好用,不错!</h4>
    </div>
  </template>
  <script>
    Vue.component('mycom3', {
      template: '#tmpl'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    })
  </script>
</body>

</html>
  • 将模板字符串,定义到script标签 ,同时,需要使用 Vue.component 来定义组件:
  • 在子组件中,如果将模板字符串,定义到了script标签中,那么,要访问子组件身上的data属性中的值,需要使用this来访问;
<script id="tmpl" type="x-template">
      <div><a href="#">登录</a> | <a href="#">注册</a></div>
</script>

Vue.component('account', {
      template: '#tmpl'
    });
  • 定义私有组件
<script src="./lib/vue-2.4.0.js"></script>
<body>
  <div id="app2">
    <mycom3></mycom3>
    <login></login>
  </div>
  <template id="tmpl2">
    <h1>这是私有的 login 组件</h1>
  </template>

  <script>
    var vm2 = new Vue({
      el: '#app2',
      data: {},
      methods: {},
      components: { // 定义实例内部私有组件的
        login: {
          template: '#tmpl2'
        }
      }
    })
  </script>
</body>

</html>

注意:无论是哪一种方式创建组建, 组件中的DOM结构,有且只能有唯一的根元素(Root Element)来进行包裹!

3、组件中展示数据和响应事件

  1. 组件可以有自己的 data 数据
  2. 组件的 data 和 实例的 data 有点不一样,实例中的 data 可以为一个对象,但是 组件中的 data 必须是一个方法
  3. 组件中的 data 除了必须为一个方法之外,这个方法内部,还必须返回一个对象才行;
  4. 组件中 的data 数据,使用方式,和实例中的 data 使用方式完全一样!!!
<script src="./lib/vue-2.4.0.js"></script>
<body>
  <div id="app">
    <mycom1></mycom1>
  </div>
  <script>
    Vue.component('mycom1', {
      template: '<h1>这是全局组件 --- {{msg}}</h1>',
      data: function () {
        return {
          msg: '这是组件的中data定义的数据'
        }
      }
    })
    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>
</body>

</html>

4、为什么组件中的data属性必须定义为一个方法并返回一个对象

当一个组件被定义, data 必须声明为返回一个初始数据对象的函数,因为组件可能被用来创建多个实例。如果 data 仍然是一个纯粹的对象,则所有的实例将共享引用同一个数据对象!通过提供 data 函数,每次创建一个新实例后,我们能够调用 data 函数,从而返回初始数据的一个全新副本数据对象

其实也很好理解,大概意思就是:

类比与引用数据类型。如果不用function return 每个组件的data都是内存的同一个地址,那一个数据改变其他也改变了,这当然就不是我们想要的。用function return 其实就相当于申明了新的变量,相互独立,自然就不会有这样的问题;js在赋值object对象时,是直接一个相同的内存地址。所以为了每个组件的data独立,采用了这种方式。
如果不是组件的话,正常data的写法可以直接写一个对象,比如data:{ msg : ' 下载 ' },但由于组件是会在多个地方引用
的,JS中直接共享对象会造成引用传递,也就是说修改了msg后所有按钮的msg都会跟着修改,所以这里用function来每次返回一个对象实例。

例子展示:

<script src="./lib/vue-2.4.0.js"></script>
<body>
  <div id="app">
    <counter></counter>
    <hr>
    <counter></counter>
    <hr>
    <counter></counter>
  </div>
  <template id="tmpl">
    <div>
      <input type="button" value="+1" @click="increment">
      <h3>{{count}}</h3>
    </div>
  </template>

  <script>
    var dataObj = { count: 0 }

    // 这是一个计数器的组件, 身上有个按钮,每当点击按钮,让 data 中的 count 值 +1
    Vue.component('counter', {
      template: '#tmpl',
      data: function () {
        // return dataObj
        return { count: 0 }
      },
      methods: {
        increment() {
          this.count++
        }
      }
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {},
      methods: {}
    });
  </script>
</body>

</html>

5、组件的切换

使用flag标识符结合v-ifv-else切换组件

 <script src="./lib/vue-2.4.0.js"></script>
<body>
  <div id="app">
    <a href="" @click.prevent="flag=true">登录</a>
    <a href="" @click.prevent="flag=false">注册</a>
    <login v-if="flag"></login>
    <register v-else="flag"></register>
  </div>
  <script>
    Vue.component('login', {
      template: '<h3>登录组件</h3>'
    })
    Vue.component('register', {
      template: '<h3>注册组件</h3>'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        flag: false
      },
      methods: {}
    });
  </script>
</body>

</html>

使用:is属性来切换不同的子组件

  1.  Vue提供了 component ,来展示对应名称的组件
  2. component 是一个占位符, :is 属性,可以用来指定要展示的组件的名称
  3. comName是可以自定义的
 <script src="./lib/vue-2.4.0.js"></script>
<body>
  <div id="app">
    <a href="" @click.prevent="comName='login'">登录</a>
    <a href="" @click.prevent="comName='register'">注册</a>
    <component :is="comName"></component>
  </div>
  <script>
    // 组件名称是 字符串
    Vue.component('login', {
      template: '<h3>登录组件</h3>'
    })

    Vue.component('register', {
      template: '<h3>注册组件</h3>'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        comName: 'login' // 当前 component 中的 :is 绑定的组件的名称
      },
      methods: {}
    });
  </script>
</body>

</html>

为组件的切换添加动画

通过 mode 属性,设置组件切换时候的 模式

 <script src="./lib/vue-2.4.0.js"></script>
 <style>
    .v-enter,
    .v-leave-to {
      opacity: 0;
      transform: translateX(150px);
    }
    .v-enter-active,
    .v-leave-active {
      transition: all 0.5s ease;
    }
  </style>
</head>
<body>
  <div id="app">
    <a href="" @click.prevent="comName='login'">登录</a>
    <a href="" @click.prevent="comName='register'">注册</a>

    <!-- 通过 mode 属性,设置组件切换时候的 模式 -->
    <transition mode="out-in">
      <component :is="comName"></component>
    </transition>

  </div>

  <script>
    // 组件名称是 字符串
    Vue.component('login', {
      template: '<h3>登录组件</h3>'
    })

    Vue.component('register', {
      template: '<h3>注册组件</h3>'
    })

    // 创建 Vue 实例,得到 ViewModel
    var vm = new Vue({
      el: '#app',
      data: {
        comName: 'login' // 当前 component 中的 :is 绑定的组件的名称
      },
      methods: {}
    });
  </script>
</body>

</html>

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值