博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Vue学习记录(二)
阅读量:4697 次
发布时间:2019-06-09

本文共 21387 字,大约阅读时间需要 71 分钟。

一、指令

  指令是Vue.js中一个重要的特性,主要提供了一种机制将数据的变化映射为DOM行为。当数据变化时,指令会依据设定好的操作对DOM进行修改,这样就可以只关注数据的变化,而不用去管理DOM的变化和状态,使得逻辑更加清晰,可维护性更好。

  1、内置指令

    1.1、v-bind

      v-bind主要用于动态绑定DOM元素属性(attribute),即元素属性实际的值由vm实例中的data属性提供的。例:

new Vue({    data: {        avatar: 'http://...'    }});

       v-bind可以简写为:,即可简写为<img :src='avatar' />。

       v-bind还拥有三种修饰符,分别为.sync、.once、.camel,作用分别如下:

        .sync:用于组件props属性,进行双向绑定,即父组件绑定传递给子组件的值,无论在哪个组件中对其进行了修改,其他组件中的这个值也会随之更新。但一般不推荐子组件直接修改父组件数据,这样会导致耦合且组件内的数据不容易维护。

        .once:同.sync一样,用于组件props属性,但进行的是单次绑定。和双向绑定刚好相反,单次绑定是将绑定数据传递给子组件后,子组件单独维护这份数据,和父组件的数据再无关系,父组件的数据发生变化不影响子组件中的数据。

        .camel:将绑定的特性名字转回驼峰命名。只能用于普通HTML属性的绑定,通常会用于svg标签下的属性。例:

输出结果即为:
    1.2、v-model

      v-model指令主要用于input、select、textarea标签中,具有lazy、number、debounce(2.0废除)、trim(2.0新增)这些修饰符。

    1.3、v-if/v-else/v-show

      v-if/v-else/v-show这三个指令主要用于根据条件展示对应的模板内容。v-if在条件为false的情况下并不进行模板的编译,而v-show则会在模板编译好之后将元素隐藏掉。v-if的切换消耗要比v-show高,但初始条件为false的情况下,v-if的初始渲染要稍快。

    1.4、v-for

      v-for也是用于模板渲染的指令,在Vue.js 2.0中做了细微调整,大致包含:

      1、参数顺序变化

      当包含参数index或key时,对象参数修改为(item, index)或(value, key),这样与JSArray对象的新方法forEach和map,以及一些对象迭代器(例如lodash)的参数能保持一致。

      2、v-bind:key

      属性track-by被b-bind:key代替。

需改为
      3、n in 10

      v-for="n in 10"中的n由原来的0~9迭代变成0~10迭代。

    1.5、v-on

      v-on指令主要用于事件绑定。例:

v-on可以简写为:

      修饰符包括.stop、.prevent、.capture、.self以及指定按键.{keyCode | keyAlias}。

      在Vue.js 2.0中,在组件上使用v-on指令只监听自定义时间,即使用$emit触发的事件;如果要监听原生事件,需要使用修饰符.native,例如<my-component v-on:click.native="onClick"></my-component>。

    1.6、v-text

      v-text,参数类型为String,作用是更新元素的textContent。{

{}}文本插值本身也会被编译成textNode的一个v-text指令。与{
{}}不同,v-text需要绑定在某个元素上,能避免未编译前的闪现问题。例:

    1.7、v-HTML

      v-HTML,参数类型为String,作用为更新元素的innerHTML,接受的字符串不会进行编译等操作,按普通HTML处理。同v-text类似,{

{
{}}}插值也会编译为节点的v-HTML指令,v-HTML也需要在某个元素上且能避免编译前闪现问题。例:

{
{ HTML }}
    1.8、v-el

      v-el指令为DOM元素注册了一个索引,使得我们可以直接访问DOM元素。语法上来说,可以通过所属实例的$els属性调用。例:

there is a el demo
vm.$els.demo.innerText // there is a el demo

      或者在vm内部通过this进行调用。

      另外,由于HTML不区分大小写,在v-el中如果使用了驼峰式命名,系统会自动转成小写。但可以使用“-”来连接你期望大写的字母。例:

There is a camelcase
There is a camelCase
vm.$els.camelcase.innerText // There is a camelcasevm.$els.camelCase.innerText // There is a camelCase
    1.9、v-ref

      v-ref指令与v-el类似,只不过v-ref作用域组件上,实例可以通过$refs访问子组件。命名方式也类似,想使用驼峰式命名的话用“-”来做连接。例:

var Message = Vue.extend({ props: ['content'], template: '

{
{ content }}

'});Vue.component('message', Message);

      从理论上来说,可以通过父组件对子组件进行任意的操作,但实际上尽量还是会采用props数据绑定,用组件间通信的方式去进行逻辑上的交互,尽量让组件只操作自己内部的数据和状态,如果组件间有通信,也通过调用组件暴露出来的接口进行通信,而不是直接跨组件修改数据。

    1.10、v-pre

      v-pre指令相对简单,就是跳过编译这个元素和子元素,显示原始的{

{}}Mustache标签,用来减少编译时间。例:

{
{ uncompiled }}
var vm = new Vue({ el: '#app', data: { uncompiled: 'This is an uncompiled element' }});

     最后输出:

{
{ uncompiled }}
    1.11、v-cloak

      v-cloak指令相当于在元素上添加了一个[v-cloak]的属性,直到关联的实例结束编译。官方推荐可以和css规则[v-cloak]{display: none; }一起使用,可以隐藏未编译的Mustache标签直到实例准备完毕。例:

{
{ msg }}
    1.12、v-once

      v-once指令是Vue.js 2.0中新增的内置指令,用于标明元素或组件只渲染一次,即使随后发生绑定数据的变化或更新,该元素或组件及包含的子元素都不会被再次编译和渲染。使用方式:

{
{ msg }}

  2、自定义指令基础

    除了内置指令外,Vue.js也提供了方法让我们可以注册自定义指令,以便封装对DOM元素的重复处理行为,提高代码复用率。

    2.1、指令的注册

      通过Vue.directive(id, definition)方法注册一个全局自定义指令,接收参数id和定义对象。id是指令的唯一标识,definition则是指令的相关属性及钩子函数。例:

Vue.directive('global-directive', definition);    // 只注册了这个命令,并没有赋予这个指令任何功能

      可以在模板中这样使用:

      而除了全局注册指令外,我们也可以通过在组件的directives选项注册一个局部的自定义指令。例:

var comp = new Vue({    directives: {        'localDirective': {}    // 可以采用驼峰式命名    }});

      该指令就只能在当前组件内通过v-local-directive的方式调用,而取法被其他组件调用。

    2.2、指令的定义对象

      在注册指令的同时,可以传入definition对象,对指令赋予一些特殊的功能。这个定义对象主要包含三个钩子函数:bind、update和unbind。

      bind:只被调用一次,在指令第一次绑定到元素上时调用。

      update:指令在bind之后以初始值为参数进行第一次调用,之后每次当绑定值发生变化时调用,update接收到的参数为newValue和oldValue。

      unbind:指令从元素上解绑时调用,只调用一次。

Vue.directive('my-directive', { bind: function() { console.log('bind', arguments); }, update: function(newValue, oldValue) { console.log('update', newValue, oldValue); }, unbind: function() { console.log('unbind', arguments); }});var vm = new Vue({ el: '#app', data: { param: 'first', isExist: true }});

    在控制台先后输入vm.param = 'second'和vm.isExist = false,整体输出如下:

bind []update first undefinedvm.param = 'second'update first second'second'vm.isExist = falseunbind []false    // 手打运行结果,具体可自己运行看输出

    另外,如果我们只需要使用update函数时,可以直接传入一个函数代替定义对象:

Vue.directive('my-directive', function(value) {    // 该函数即为update函数});

     上述例子中,可以使用my-directive指令绑定的值是data中的param属性。也可以直接绑定字符串常量,或使用字面修饰符,但这样的话需要注意update方法将只调用一次,因为普通字符串不能响应数据变化。例:

//value为undefined,因为data中没有对应的属性
//value为constant,绑定字符串需要加单引号
//value为constant,利用字面修饰符后无需使用单引号

     除了字符串外,指令也接受对象字面量或任意合法的JavaScript表达式。例:

    注意此时对象字面量不需要用单引号括起来,这和字符串常量不一样。

  2.3、指令实例属性 

     除了了解指令的生命周期外,还需要知道指令中能调用的相关属性,以便对相关DOM进行操作。在指令的钩子函数内,可以通过this来调用指令实例。

    el:指令绑定的元素。

    vm:该指令的上下文ViewModel,可以为new Vue()的实例,也可以为组件实例。

    expression:指令的表达式,不包括参数和过滤器。

    arg:指令的参数。

    name:指令的名字,不包括v-前缀。

    modifiers:一个对象,包含指令的修饰符。

    descriptor:一个对象,包含指令的解析结果。 

Vue.directive('my-msg', { bind: function() { console.log('~~~~~~~~bind~~~~~~~~~~~'); console.log('el', this.el); console.log('name', name); console.log('vm', this.vm); console.log('expression', this.expression); console.log('arg', this.arg); console.log('modifiers', this.modifiers); console.log('descriptor', this.descriptor); }, update: function(newValue, oldValue) { var keys = Object.keys(this.modifiers); window[this.arg][keys[0]](newValue); }, unbind: function() { }});var vm = new Vue({ el: '#app', data: { content: 'there is the content' }});
   2.4、元素指令

     元素指令是Vue.js的一种特殊指令,普通指令需要绑定在某个具体的DOM元素上,但元素指令可以单独存在,从使用方式上看更像是一个组件,但本身内部的实例属性和钩子函数是和指令一样的。例:

// 普通指令使用方式
// 元素指令使用方式

    元素指令的注册方式和普通指令类似,也有全局注册和局部注册两种。

Vue.elementDirective(;my-ele-directive');    // 全局注册方式var Comp = Vue.extend({    ...    // 省略了其他参数    elementDirective: {        'eleDirective': {}    }});Vue.component('comp', Comp);

    元素指令不能接受参数或表达式,但可以读取元素特性从而决定行为。而且当编译过程中遇到一个元素指令时,Vue.js将忽略该元素及其子元素,只有元素指令本身才可以操作该元素及其子元素。

    Vue.js 2.0中取消了这个特性,推荐使用组件来实现需要的业务。

3、指令的高级选项

  Vue.js指令定义对象中除了钩子函数外,还有一些其他选项。

  3.1、params  

     定义对象中可以接受一个params数组,Vue.js编译器将自动提取自定义指令绑定元素上的这些属性。例:

Vue.directive('my-advance-directive', { params: ['a'], bind: function() { console.log('params', this.params);

    除了直接传入数值外,params支持绑定动态数据,并且可以设定一个watcher监听,但是护具变化时,会调用这个回调函数。例:

// 当然可以简写成
Vue.directive('my-advance-directive', { params: ['a'], paramWatchers: { a: function(val, oldVal) { console.log('watcher:', val, oldVal); } }, bind: function() { console.log('params', this.params); }});var vm = new Vue({ el: '#app', data: { a: 'dynamic data' }});

     输出结果为:

params Object{a: "dynamic data"}vm.a = 123watcher:123 dynamic data123
  3.2、deep

     当自定义指令作用域一个对象上时,可以使用deep选项来监听对象内部发生的变化。例:

Vue.directive('my-deep-directive', { deep: true, update: function(newValue, oldValue) { console.log('deep', newValue.a.b); }});Vue.directive('my-nodeep-directive', { update: function(newValue, oldValue) { console.log('nodeep', newValue.a.b); }});var vm = new Vue({ el: '#app', data: { obj: { a: { b: 'inner' } } }});

      运行后,在控制台中输入vm.obj.a.b = 'inner changed',只有my-deep-directive调用了update函数,输出了改变后的值。

    输出结果为:

deep innernodeep innervm.obj.a.b = 'inner changed'deep inner changed

    Vue.js 2.0中废弃了该选项。

  3.3、twoWay

    在自定义指令中,如果需要向Vue实例写回数据,就需要在定义对象中使用twoWay: true,这样可以在指令中使用this.set(value)来写回数据。

Vue.directive('my-twoway-directive', {    twoWay: true,    bind: function() {        this.handler = function() {            console.log('value changed:', this.el.value);            this.set(this.el.value);        }.bind(this)        this.el.addEventListener('input', this.handler)    },    unbind: function() {        this.el.removeEventListener('input', this.handler)    }});var vm = new Vue({    el: '#app',    data: {        param: 'first'    }});

    此时在input中输入文字,然后在控制台中输入vm.param即可观察到实例的param属性已被改变。

    需要注意的是, 如果没有设定twoWay: true,就在自定义指令中调用this.set(),Vue.js会抛出异常。

  3.4、acceptStatement

    选项acceptStatement: true可以允许自定义指令接受内联语句,同时update函数接收的值是一个函数,在调用该函数时,它将在所属实例作用域内运行。

Vue.directive('my-directice', { acceptStatement: true, update: function(fn) { }});var vm = new Vue({ el:'#app', data: { i: 0 }});

     如果在update函数中,运行fn(),则会执行内联语句i++,此时vm.i = 1.但更改vm.i并不会触发update函数。

    需要当心的是,如果此时没有设定acceptSatement: true,该指令会陷入一个死循环中。v-my-directive接受到i的值 每次都在变化,会重复调用update函数,最终导致Vue.js抛出异常。

  3.5、terminal

    选项terminal的作用是阻止Vue.js便利这个元素及其内部元素,并由该指令本身去编译绑定元素及其内部元素。内置的指令v-if和v-for都是terminal指令。

    使用terminal选项是一个相对复杂的过程,需要对Vue.js的编译过程有一定的了解。

...

header

body

footer

var FragmentFactory = Vue.FragmentFactory    // Vue.js全局API,用来创造fragment的工厂函数,fragment中包含了具体的scope和DOM元素,可以看成一个独立的组件或者实例。var remove = Vue.util.remove    // Vue.js工具类函数,移除DOM元素var createAnchor = Vue.util.createAnchor    // 创建锚点,锚点在debug模式下是注释节点,非debug模式下是文本节点,主要作用是标记DOM元素的插入和移除Vue.directive('inject', {    terminal: true,    bind: function() {        var container = document.getElementById(this.arg)    // 获取需要注入到的DOM元素        this.anchor = createAnchor('v-inject')    // 创建v-inject锚点        container.appendChild(this.anchor)    // 锚点挂载到注入节点中        remove(this.el)    // 移除指令绑定的元素        var factory = new FragmentFactory(this.vm, this.el)    // 创建fragment        this.frag = factory.create(this._host, this._scope, this._frag)                // this._host 用于表示存在内容分发时的父组件        // this._scope 用于表示存在v-for时的作用域        // this._frag 用于表示该指令的父fragment        this.frag.before(this.anchor)    },    unbind: function() {        this.frag.remove()        remove(this.anchor)    }});
  3.6、priority

     选项priority即为指定指令的优先级。普通指令默认是1000,terminal指令默认为2000.同一元素上优先级高的指令会比其他指令处理的早一些,相同优先级则按出现顺序依次处理。以下为内置指令的优先级顺序:

export const ON = 700export const MODEL = 800export const BIND = 850export const TRANSITION = 1100export const EL =1500export const COMPONENT = 1500export const PARTIAL = 1750export const IF = 2100export const FOR = 2200export const SLOT = 2300

  4、 指令在Vue.js 2.0中的变化

    指令在Vue.js2.0中发生了较大的变化。总的来说,Vue.js2.0中的指令功能更为单一,很多和组件重复的功能和作用都进行了删除,指令也更专注于本身作用域的操作,而尽量不去影响指令外的DOM元素及数据。

     4.1、新的钩子函数

       钩子函数增加了一个componentUpdated,当整个组件都完成了update状态后即所有的DOM都更新后调用该钩子函数,无论指令接受的参数是否发生变化。

    4.2、钩子函数实例和参数变化

       在Vue.js2.0中取消了指令实例这一概念,即在钩子函数中的this并不能指向指令的相关属性。指令的相关属性均通过参数的形式传递给钩子函数。

Vue.directive('my-directive', {    bind: function(el, binding, vnode) {        console.log('~~~~~~~~~~~~~~~~~bind~~~~~~~~~~');        console.log('el', el);        console.log('binding', binding);        console.log('vnode', vnode);    },    update: function(el, binding, vnode, lodVNode) {        ...    },    componentUpdated(el, binding, vnode, oldVNode) {        ...    },    unbind: function(el, binding, vnode) {        ...    }});

       在Vue.js1.0中的实例中的属性大部分都能在binding中找到,vnode则主要包含了节点的相关信息,有点类似于fragment的作用。

    4.3、update函数触发变化

       钩子函数update对比Vue.js1.0也有以下两个变化:

        (1)指令绑定bind函数执行后不直接调用update函数。

        (2)只要组件发生重绘,无论指令接受的值是否发生变化,均会调用update函数。如果需要过滤不必要的更新,则可以使用binding.value == binding.olbValue来判断。

    4.4、参数binding对象

      钩子函数接受的参数binding对象为不可更改,强行设定binding.value的值并不会引起实际的改动。如果非要通过这种方式进行修改的话,只能通过el直接修改DOM元素。

二、过滤器

  Vue.js允许在表达式后面添加可选的过滤器,以管道符表示,例:

{
{ message | capitalize }}

  过滤器的本质是一个函数,接受管道符前面的值作为初始值,同事也能接受额外的参数,返回值为经过处理后的输出值。多个过滤器也可以进行串联。例:

{
{ message | filterA 'arg1' 'arg2' }}{
{ message | filterA | filterB }}
  1、过滤器注册

     Vue.js提供了全局方法Vue.filter()注册一个自定义过滤器,接受过滤器ID和过滤器函数两个参数。例:

Vue.filter('date', function(value) {    if(!value instanceof Date) return value;    return value.toLocaleDateString();});

    这样注册之后,就可以在vm实力的模板中使用这个过滤器了。

{
{ date | date }}
var vm = new Vue({ el: '#app', data: { date: new Date() }});

    除了初始值之外,过滤器也能接受任意数量的参数。例:

Vue.filter('date', function(value, format) {    var o = {        "M+":value.getMonth() +1,     // 月份        "d+":value.getDate(),     // 日        "h+":value.getHours(),     // 小时        "m+":value.getMinutes(),     // 分        "s+":value.getSeconds(),     // 秒};if(/(y+)/.test(format))    format = format.replace(RegExp.$1, (value.getFullYear() + "").substr(4 - RegExp.$1.length));for(var k  in o)    if(new RegExp("(" + k + ")").test(format))        format = format.replace(RegExp.$1, (RegExp.$1.length == 1)            ? (o[k])            : (("00" + o[k]).substr(("" + o[k]).length)));    return format;});

     使用方式即为:

{
{ date | date 'yyyy-MM-dd hh:mm:ss' }} // -> 2018-04-25 10:46:46 即可按格式输出当前时间
   2、双向过滤器

     之前提及的过滤器都是在数据输出到视图之前,对数据进行转化显示,但不影响数据本身。Vue.js也提供了在改变视图中数据的值,写回data绑定属性中的过滤器,称为双向过滤器。例:

// 该过滤器的作用是处理价钱的转化,一般数据库中保存的单位都为分,避免浮点运算Vue.filter('cents', {    read: function(value) {        return (value / 100).toFixed(2);    },    write: function(value) {        return value * 100;    }});var vm = new Vue({    el: '#app',    data: {        price: 150    }});
   3、动态参数

     过滤器除了能接受单引号('')括起来的参数外,也支持接受在vm实例中绑定的数据,称之为动态参数。使用区别就在于不需要单引号将参数括起来。例:

{
{ data | dynamic price }}
Vue.filter('dynamic', function(data, price) { return date.toLocaleDateString() + ':' + price;});var vm = new Vue({ el: '#app', data: { date: new Date(), price: 150 }});

    过滤器中接受到的price参数即为vm.price。

  4、过滤器在Vue.js2.0中的变化

    (1)取消了所有内置过滤器,即capitalize,json等。建议尽量使用单独的插件来按需假如你所需要的过滤器。

    (2)取消了对v-model和v-on的支持,过滤器只能使用在{

{}}标签中。

    (3)修改了过滤器参数的使用方式,采用函数的形式而不是空格来标记参数。例如:{

{ date | date('yyyy-MM-dd') }}。

 三、过渡

   过渡系统是Vue.js为DOM动画效果提供的一个特性,它能在元素从DOM中插入或移除时触发CSS过渡(transition)和动画(animation),也就是说在DOM元素发生变化时为其添加特定的class类名,从而产生过渡效果。除了CSS过渡外,Vue.js的过渡系统也支持javascript的过渡,通过暴露过渡系统的钩子函数,可以在DOM变化的特定时机对其进行属性的操作,产生动画效果。

  1、CSS过渡

    1.1、CSS过渡的用法
var vm = new Vue({ el: '#app', data: { show: false }});

     首先在模板中用transition绑定一个DOM元素,并且使用v-if指令元素先处于未被编译状态。然后在控制台内手动调用vm.show = true,就可以看到DOM元素最后输出为:

 

    DOM元素完成编译后,过渡系统自动给元素添加了一个my-startup-transition的class类名。为了让这个效果更明显一点,可以提前给这个类名添加一点CSS样式:

.my-startup-transition {
transition: all 1s ease; width: 100px; height: 100px; background: black; opacity: 1;}

     此时再重新刷新并手动运行vm.show = true,发现最终样式效果是加载上去了,但并没有出现transition效果。这是由于在编译v-if后,div直接挂载到body并添加my-startup-transition类名这两个过程中浏览器仅进行了一次重绘,这对于div来说并没有产生属性的更新,所以没有执行css transition的效果。为了解决这个问题,Vue.js的过渡系统给元素插入及移除时分别添加了2个类名:*-enter和*-leave,*即为transition绑定的字符串,本例中即为m-startup。所以在上述例子中,还需要添加两个类名样式,即my-startup-enter,my-startup-leave:

.my-startup-enter,  .my-startup-leave {
height: 0; opacity: 0; }

    此时再重复之前的操作,就可以看到过渡效果了。需要注意的是,这两个类名的优先级要高于.my-startup-transition,不然被my-startup-transition覆盖后就失效了。

    同样,也可以通过CSS的animation属性来实现过渡的效果,例:

animation
var vm = new Vue({ el: '#app', data: { animation: false }});

    同样,更高vm.animation为true后即可看到过渡效果。

    除了直接在元素上添加transition = "name"外,Vue.js也支持动态绑定CSS名称,可用于多个元素需要多个过渡效果的场景。例:

// 也可以简写成‘
var vm = new Vue({ el: '#app', data: { show: false, transitionName: 'fade' }});

     Vue.js本身并不提供内置的过渡CSS样式,仅仅是提供了过渡需要使用的加载或移除时机,这样更便于灵活地按需去设计过渡样式。

      1.2、CSS过渡钩子函数

    Vue.js提供了在插入或DOM元素时类名变化的钩子函数,可以通过Vue.transition('name', {})的方式来执行具体的函数操作。例:

Vue.transition('my-startup', {    beforeEnter: function(el) {        console.log('boforeEnter', el.className);    },    enter: function(el) {        console.log('enter', el.className);    },    afterEnter: function(el) {        console.log('afterEnter', el.className);    },    enterCancelled: function(el) {        console.log('enterCancelled', el.className);    },    beforeEnter: function(el) {        console.log('boforeEnter', el.className);    },    enter: function(el) {        console.log('enter', el.className);    },    afterEnter: function(el) {        console.log('afterEnter', el.className);    },    enterCancelled: function(el) {        console.log('enterCancelled', el.className);    }

     在控制台里执行vm.show = true,输出结果如下:

vm.show = truebeforeEnter my-startup-transitionenter my-startup-transition my-startup-entertrueafterEnter my-startup-transition

    这样,我们能很清楚地看到钩子函数执行的顺序以及元素类名的变化。同样的,还可以再次更改vm.show的值置为false,结果如下:

vm.show = falsebeforeLeave my-startup-transitionleave my-startup-transition my-startup-leavefalseafterLeave my-startup-transition

    由于元素在使用CSS的transition和animation时,系统的流程不完全一样。所以先以transition为例,总结下过渡系统的流程。

    当vm.show = true时,

    (1)调用beforeEnter函数。

    (2)添加enter类名到元素上。

    (3)将元素插入到DOM中。

    (4)调用enter函数。

    (5)强制reflow一次,然后移除enter类名,触发过渡效果。

    (6)如果此时元素被删除,则触发enterCancelled函数。

    (7)监听transitionend事件,过渡结束后调用afterEnter函数。

    当vm.show = false时,

    (1)调用beforeLeave函数。

    (2)添加v-leave类名,触发过渡效果。

    (3)调用leave函数。

    (4)如果此时元素被删除,则触发leaveCancelled函数。

    (5)监听transitionend事件,删除元素及*-leave类名。

    (6)调用afterLeave函数。

    如果使用animation作为过渡的话,在DOM插入时,*-enter类名不会立即删除,而是在animationend事件触发时删除。

    另外,enter和leave函数都有第二个可选的毁掉参数,用于控制过渡何时结束,而不是监听transitionend和animationend事件,例:

Vue.transition('my-done', {    enter: function(el, done) {        this.enterTime = new Date();        setTimeout(done, 500);    },    afterEnter: function(el) {        console.log('afterEnter', new Date() - this.enterTime);    }});var vm = new Vue({    el: '#app',    data: {        done: false    }});

    输出结果如下:

vm.done = truetrueafterEnter 500

    此时afterEnter函数执行的事件就不是my-done-transition样式中的2s之后,而是done调用的500ms之后。需要注意的是 ,如果在enter和leave中声明了形参done,但没有调用,则不会触发afterEnter函数。

  1.3 显示声明过渡类型

     Vue.js可以指定过渡元素监听的结束事件的类型,例:

Vue.transition('done-type', {    type: 'animation'});

    此时Vue.js就只监听元素的animationend事件,避免元素上还存在transition时导致的结束事件触发不一样。

  1.4 自定义过渡类名

    除了使用默认的类名*-enter、*-leave外,Vue.js也允许我们自定义过渡类名,例:

Vue.transition('my-startup', {    enterClass: 'fadeIn',    leaveClass: 'fadeOut'});

     我们可以通过上述钩子函数的例子,观测元素的类名变化:

vm.show = truebeforeEnter my-startup-transitionenter my-startup-transition my-startup-entertrueafterEnter my-startup-transitionvm.show = falsebeforeLeave my-startup-transitionleave my-startup-transition my-startup-leavefalseafterLeave my-startup-transition 

     Vue.js官方推荐了一个CSS动画库,animate.css,配合自定义过渡类名使用,可以达到非常不错的效果。只需要引入一个CSS文件,http://cdn.bootcss.com/animate.css/3.5.2/animate.min.css,就可以使用里面的预设动画。例:

Vue.transition('bounce', {    enterClass: 'bounceIn',    leaveClass: 'bounceOut'});
bounce effect

    在使用animate.css时,需要先给元素附上animated类名,然后再添加预设的动效类名,例如上例中的bounceIn、bounceOut,这样就能看到动画效果。这个库提供了多种强调展示(例如弹性、抖动)、渐入渐出、翻转、旋转、放大缩小等效果。所有的效果可以访问官网地址http://daneden.github.io/animate.css/在线观看。

    2. JavaScript过渡

      Vue.js也可以和一些JavaScript动画库配合使用,这里只需要调用JavaScript钩子函数,而不需要定义CSS样式。transition接受选项css: false,将直接跳过CSS检测,避免CSS规则干扰过渡,而且需要在enter和leave钩子函数中调用done函数,明确过渡结束事件。此处将引入Velocity.js来配合使用JavaScript过渡。

    2.1 Velocity.js

     Velocity.js是一款搞笑的动画引擎,可以单独使用也可以配合jQuery使用。它拥有和jQuery的animate一样的api接口,但比jQuery在动画处理方面更强大、更流畅,以及模拟了一些现实世界的运动,例如弹性动画等。

    Velocity.js可以当做jQuery的插件使用,例:

$element.velocity({    left: "100px"}, 500, "swing", function() {    console.log("done");});$element.velocity({    left: "100px"}, {    duration: 500,    easing: "swing",    complete: function() {        console.log("done");    }});

    也可以单独使用,例:

var el = document.getElementById(id);Velocity(el, {    left: '100px'}, 500, 'swing', done);
    2.2 JavaScript过渡使用  

     可以通过以下方式注册一个自定义的JavaScript过渡:

Vue.transition('my-velocity', {    css: false,    enter: fumction(el, done) {        Velocity(el, { left: '100px' }, 500, 'swing', done);    },    enterCancelled: function(el) {        Velocity(el, 'stop');    },    leave: fumction(el, done) {        Velocity(el, { left: '0px' }, 500, 'swing', done);    },    leaveCancelled: function(el) {        Velocity(el, 'stop');    }});

    运行上述代码,在设置vm.velocity = true后,过渡系统即会调用enter钩子函数,通过Velocity对DOM操作展现动画效果,然后强制调用done函数,明确结束过渡效果。

  3.过渡系统在Vue.js 2.0中的变化

    过渡系统在Vue.js 2.0中也发生了比较大的变化,借鉴了ReactJS CSSTransitionGroup的一些相关设定和命名。

    3.1 用法变化

     新的过渡系统中取消了v-transition这个指令,新增了名为transition的内置标签,用法变更为:

content

    transition标签为一个抽象组件,并不会额外渲染一个DOM元素,仅仅是用于包裹过渡元素及触发过渡行为。v-if、v-show等指令仍旧标记在内容元素上,并不会作用于transition标签上。

    transition标签能接受的参数与Vue.js 1.0中注册的transition接受的选项类似。

    1.name

      同v-transition中接受的参数,自动生成对应的name-enter,name-enter-active类名。

     2.appear

       元素首次渲染的时候是否启用transition,默认值为false。即v-if绑定值初始为true时,首次渲染时是否调用transition效果。在Vue.js 1.0中,v-if如果初始值为true的话,首次渲染时无法使用transition效果的,只有v-show能使用。

    3.css

      同Vue.js 1.0的CSS选项,如果设置为true,则只监听钩子函数的调用。

    4.type

      同Vue.js 1.0的type选项,设置监听的CSS动画结束事件的类型。

    5.mode

      控制过渡插入/移除的先后顺序,主要用于元素切换时。可供选择的值有“out-in”、“in-out”,如果不设置,则同时调用。例:

{

{ ok }}

// 这里的:key="ok"主要用于强制替换元素,展现出in-out/out-in效果

       当ok在true和false切换时,mode="out-in"决定先移除<p>false</p>,等过渡结束后,再插入<p>true</p>元素,mode="in-out"则相反。

    6.钩子函数

      enterClass、leaveClass、enterActiveClass、leaveActiveClass、appearClass、appearActiveClass,可以分别自定义各阶段的class类名。

      总的来说,在Vue.js 2.0中我们可以直接使用transition标签并设定其属性来定义一个过渡效果,而不需要像在Vue.js 1.0中通过Vue.transition()语句来定义。例:

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

    

 

转载于:https://www.cnblogs.com/minozMin/p/8855208.html

你可能感兴趣的文章
使用Siege进行WEB压力测试
查看>>
斑马为什么有条纹?
查看>>
android多层树形结构列表学习笔记
查看>>
Android_去掉EditText控件周围橙色高亮区域
查看>>
《构建之法》第一、二、十六章阅读笔记
查看>>
arrow:让Python的日期与时间变的更好
查看>>
(转)Excel的 OleDb 连接串的格式(连接Excel 2003-2013)
查看>>
Java并发编程
查看>>
Git Stash用法
查看>>
sql server 2008学习8 sql server存储和索引结构
查看>>
Jquery radio选中
查看>>
postgressql数据库中limit offset使用
查看>>
测试思想-集成测试 关于接口测试 Part 2
查看>>
php生成器使用总结
查看>>
T-SQL中的indexof函数
查看>>
javascript基础之数组(Array)对象
查看>>
mysql DML DDL DCL
查看>>
RAMPS1.4 3d打印控制板接线与测试1
查看>>
python with语句中的变量有作用域吗?
查看>>
24@Servlet_day03
查看>>