Vue的计算属性-过滤器-添加过渡动画的几种方式

Vue的计算属性:computed

这里处理数据的要求是:让显示变量 message 的字符串翻转

<div id="app">
    <!--使用Vue计算属性不能在后面加上(),因为它是一个属性不是函数(方法)-->
    <p>{{reversedMessage}}</p>
</div>
<script>
//2.创建Vue的实例对象-->这里就是MVVM中的View Model
    let vue = new Vue({
        //3.告诉Vue的实例对象,将来需要控制界面的上的哪个区域
        el:"#app",
        //4.告诉Vue的实例对象,被控制区域的数据是什么 -->这里就是MVVM中的Model
        data:{
            message:"abcdefg"
        },
        //5.专门用于储存监听事件回调函数
        methods:{},
        //6.专门用于定义计算属性的
        computed: {
            // 计算属性的 getter
            reversedMessage: function () {
                // `this` 指向 vm 实例
                let res = this.message.split('').reverse().join('');
                return res;
            }
        }
    });
</script>

结果:

计算属性和函数的区别:

  • 函数的特点:每次调用都会执行;
  • 计算属性的特点:只要返回的结果没有发生变化,那么计算属性只会被执行一次;
  • 函数的应用场景:如果数据需要经常发生变化,推荐使用函数处理数据
  • 计算属性的应用场景:如果数据发生变化的频率不高,推荐使用计算属性处理数据,因为计算属性会将返回的结果缓存起来 如果返回的数据不会频繁的发生改变,使用计算属性会比函数的性能高;
<div id="app">
     <p>{{msg1()}}</p>
     <p>{{msg1()}}</p>
     <p>{{msg1()}}</p>
</div>

let vue = new Vue({
       el:"#app",
       data:{ 
          message:"abcdefg"
       },
       //专门用于储存监听事件回调函数
       methods:{
           /*函数的特点:每次调用都会执行*/
           msg1(){
               console.log("msg1被执行了");
               let res = this.message.split('').reverse().join('');
               return res;
           }
       }
   });

函数处理数据的结果:
<div id="app">
    <p>{{reversedMessage}}</p>
    <p>{{reversedMessage}}</p>
    <p>{{reversedMessage}}</p>
</div>

let vue = new Vue({
        el:"#app",
        data:{
            message:"abcdefg"
        },
        //专门用于储存监听事件回调函数
        methods:{
        },
        //专门用于定义计算属性的
        computed: {
            /*计算属性的特点:只要返回的结果没有发生变化,那么计算属性只会被执行一次 */
            // 计算属性的 getter
            reversedMessage: function () {
                console.log("reversedMessage被执行了");
                // `this` 指向 vm 实例
                let res = this.message.split('').reverse().join('');
                return res;
            }
        }
    });

计算属性处理数据的结果:

Vue的过滤器:filter/filters

Vue.js 允许你自定义过滤器,可被用于一些常见的文本格式化。过滤器可以用在两个地方:双花括号插值和 v-bind 表达式。过滤器应该被添加在 JavaScript 表达式的尾部,由“管道”符号“|”指示;

  • 自定义全局过滤器 :在任何一个vue实例控制区域内都可以使用
<div id="app">
<!--Vue会把name交给指定的过滤器处理之后,再把处理后的结果插入到指定的元素中-->
    <p>{{name|formatStr1|formatStr2}}</p>
</div>

//自定义全局的过滤器 
    /*接受两个参数:1.过滤器名称 2.处理数据的函数
       注意点:默认情况下处理数据的函数接受一个参数,就是当前要被处理的数据*/
    Vue.filter('formatStr1', function (value) {
        value = value.replace(/学院/g,"大学");
        console.log(value);
        return value;
    });
    Vue.filter('formatStr2', function (value) {
        value = value.replace(/大学/g,"幼儿园");
        console.log(value);
        return value;
    });
//Vue的实例对象中的Model
data:{
            name:"南方学院,北方学院,东方学院,西方学院"
        },

结果:
  • 自定义局部过滤器 :只能在自定义的内个vue实例控制区域内使用
<div id="app1">
    <p>{{name|formatStr1}}</p>
</div>
<div id="app2">
    <!--Vue会把name交给指定的过滤器处理之后,再把处理后的结果插入到指定的元素中-->
    <p>{{name|formatStr2}}</p>
</div>

<script>
let vue1 = new Vue({
         el:"#app1",
         data:{
             name:"南方学院,北方学院,东方学院,西方学院"
      },
        //专门用于储存监听事件回调函数
        methods:{},
        //专门用于定义计算属性的
        computed:{},
        //专门用于定义局部过滤器的
        filters:{
         
        }
    });
 let vue2 = new Vue({
        el:"#app2",
        data:{
            name:"南方学院,北方学院,东方学院,西方学院"
        },
        //专门用于储存监听事件回调函数
        methods:{},
        //专门用于定义计算属性的
        computed:{},
        //专门用于定义局部过滤器的
        filters:{
            "formatStr2":function (value) {
                value = value.replace(/学院/g,"大学");
                console.log(value);
                return value;
            }
        }
    });
</script>

结果:
  • 过滤器常用于格式化时间
<div id="app">
    <p>{{time | dateFormart("yyyy-MM-dd")}}</p>
</div>
<script>
    //自定义全局的过滤器
    /*接受两个参数:1.过滤器名称 2.处理数据的函数
       注意点:默认情况下处理数据的函数接受一个参数,就是当前要被处理的数据
              在使用过滤器的时候,可以再过滤器的名称后面加()
              如果给过滤器的名称后面加上(),就可以给过滤器传递参数*/
    Vue.filter("dateFormart", function (value, fmStr) {
        // console.log(fmStr);    // yyyy-MM-dd
        let date = new Date(value);
        let year = date.getFullYear();
        let month = date.getMonth() + 1 + "";
        let day = date.getDate() + "";
        let hour = date.getHours() + "";
        let minute = date.getMinutes() + "";
        let second = date.getSeconds() + "";
        if(fmStr && fmStr === "yyyy-MM-dd"){     //过滤器dateFormart是否传递了参数且参数格式为 yyyy-MM-dd
            return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")}`;
        }
        return `${year}-${month.padStart(2, "0")}-${day.padStart(2, "0")} ${hour.padStart(2, "0")}:${minute.padStart(2, "0")}:${second.padStart(2, "0")}`;
    });
    //2.创建Vue的实例对象-->这里就是MVVM中的View Model
    let vue = new Vue({
        //3.告诉Vue的实例对象,将来需要控制界面的上的哪个区域
        el:"#app",
        //4.告诉Vue的实例对象,被控制区域的数据是什么 -->这里就是MVVM中的Model
        data:{
            time: Date.now()
        },
        //5.专门用于储存监听事件回调函数
        methods:{},
        //6.专门用于定义计算属性的
        computed:{}
    });
</script>

padStart()方法用另一个字符串填充当前字符串(重复,如果需要的话),以便产生的字符串达到给定的长度。
语法:str.padStart(当前字符串需要填充到的目标长度。 填充字符串)


Vue控制元素添加过渡动画

Vue 提供了 transition 的封装组件,在下列情形中,可以给任何元素和组件添加进入/离开过渡

  • 使用默认类名(v-xxx)来指定过渡动画
    1.将执行动画的元素添加到transition组件中
    2.当transition组件显示时会自动查找v-enter/v-enter-active/v-enter-to;
    当transition组件隐藏时会自动查找v-leave/v-leave-active/v-leave-to;
过渡的类名
   <!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>使用默认类名(v-xxx)来指定过渡动画</title>
        <script src="js/vue.js"></script>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            #app{
                position:absolute;
                left:50%;
                top:50%;
                margin-left:-50px;
                margin-top:-50px;
            
            }
            .box{
                font-size: 20px;
                color: palevioletred;
                margin-top: 20px;
            }
            .v-enter{
                opacity: 0;
            }
            .v-enter-active{
                transition: all 1s;
            }
            .v-enter-to{
                opacity: 1;
            }
            .v-leave{
                opacity: 1;
            }
            .v-leave-active{
                transition: all 1s;
            }
            .v-leave-to{
                opacity: 0;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <button type="button" @click="toggle">
                toggle
            </button>
            <transition>
                <p class="box" v-if="isShow">Hello</p>
            </transition>
        </div>
        <script type="text/javascript">
            let vue = new Vue({
                el:"#app",
                data:{
                    isShow:false
                },
                methods:{
                    toggle(){
                        this.isShow = !this.isShow;
                    }
                },
                computed:{}
            });
        </script>
    </body>
</html>

效果:点击按钮后显示,再次点击后隐藏
  • 使用自定义类名前缀(yyy-xx)来指定过渡动画(transition name="yyy")
    注意点:
     1.一个transition组件中只能有一个执行动画的元素;
     2.想要元素一开始就显示过渡动画,需要在包裹执行动画的元素的transition组件上添加appear属性;
     3.如果有多个transition组件同时执行不同的过渡动画,需要在包裹执行动画的元素的transition组件上添加name="xxx"查找类名的前缀,过渡动画的类名以什么开头就写什么;
     根据类名绑定的过渡动画执行完毕后会复位,应为在执行的过程中类名被绑定到元素上,执行完毕后绑定的类名的消失了
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>使用自定义类名前缀(yyy-xx)来指定过渡动画</title>
        <script src="js/vue.js"></script>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            #app{
                position: absolute;
                left: 50%;
                top: 50%;
                margin-left:-50px;
                margin-top:-50px;
            }
            .box{
                font-size: 25px;
                color: plum;
                text-align: center;
                margin-top: 20px;
            }
            .slide-fade-enter{
                opacity: 0;
            }
            .slide-fade-enter-active{
                transition: all .8s ease;
            }
            .slide-fade-enter-to{
                opacity: 1;
            }
            .slide-fade-leave{
                opacity: 1;
            }
            .slide-fade-leave-active{
                transition: all .8s cubic-bezier(1.0, 0.5, 0.8, 1.0);  /*贝塞尔曲线*/
            }
            .slide-fade-leave-to{
                opacity: 0;
                transform: translateX(50px);  /*向右平移50px*/
            }
        </style>
    </head>
    <body>
        <div id="app">
            <button type="button" @click="toggle">
                toggle render
            </button>
            <!--加appear:一开始就出来-->
            <transition appear name="slide-fade">   
                <p class="box" v-if="isShow">Hello</p>
            </transition>
        </div>
        <script type="text/javascript">
            let vue = new Vue({
                el:"#app",
                data:{
                    isShow:true
                },
                methods:{
                    toggle(){
                        this.isShow = !this.isShow;
                    }
                },
                computed:{}
            });
        </script>
    </body>
</html>

效果:打开界面一开始就显示Hello,点击按钮后Hello向右淡出
  • 使用JS钩子函数来指定过渡动画
    v-on:before-enter="beforeEnter" 进去动画之前
    v-on:enter="enter" 进去动画执行过程中
    v-on:after-enter="afterEnter" 进去动画完成之后
    v-on:enter-cancelled="enterCancelled" 进去动画被取消
    温馨提示:如果你只想设置组件过渡进入的效果而不想有组件过渡离开的效果,这时你就可以用钩子函数,只设置beforeEnter、enter、afterEnter这几个钩子函数就可以了。

    v-on:before-leave="beforeLeave" 离开动画之前
    v-on:leave="leave" 离开动画执行过程中
    v-on:after-leave="afterLeave" 离开动画完成之后
    v-on:leave-cancelled="leaveCancelled" 离开动画被取消

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>使用JS钩子函数来指定过渡动画</title>
        <script src="js/vue.js"></script>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            #app{
                position: absolute;
                left: 50%;
                top: 50%;
                margin-left: -50px;
                margin-top: -50px;
            }
            .box{
                font-size: '1.4rem';
                color: #DB7093;
                margin-top: 20px;
            }
            .v-enter{
                opacity: 0;
            }
            .v-enter-to{
                opacity: 1;
                 margin-left: 500px;
            }
            .v-enter-active{
                transition: all 3s;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <button @click="toggle">toggle</button>
              <!--注意点:虽然是通过vue钩子函数来实现过渡动画,
                            但默认vue还是回去查找类名,所以为了不让vue去查找名
                            可以给transition添加v-bind:css="false"
                 -->
            <transition appear
                        v-bind:css="false"
                        v-on:before-enter="beforeEnter"
                        v-on:enter="enter"
                        v-on:after-enter="afterEnter"
            >
                <p class="box" v-if="isShow">Demo</p>
            </transition>
        </div>
        
        <script type="text/javascript">
            let vue = new Vue({
                el:"#app",
                data:{
                    isShow:false
                },
                methods:{
                    toggle(){
                        this.isShow = !this.isShow;
                    },
                    beforeEnter(el){//el是要执行过渡动画的元素
                        el.style.opacity = 0;
                        el.style.transformOrigin = 'left'
                    },
                    enter(el,done){//done是回调函数,告诉Vue我的动画已经执行完毕了
                        /*
                         注意点:如果通过JS钩子函数来实现过度动画
                         那么必须在动画执行过程的回调函数中写上
                         el.offsetWidth或el.offsetHeight
                        */
                        el.offsetWidth;
                        
                        el.style.transition = "all 3s";
                        /*
                         注意点:想要元素一开始就显示过渡动画
                         需要在包裹执行动画的元素的transition组件上添加appear
                         还需要在延迟一下在调用done();
                        */
                        setTimeout(function () {
                            done();
                        },0);
                    },
                    afterEnter(el){
                        el.style.opacity = 1;
                        el.style.transform = "translateX(15px) rotateZ(50deg)";
                    }
                },
                computed:{}
            })
        </script>
    </body>
</html>

效果:点击按钮后Demo淡出并开始旋转,在淡出
  • 使用自定义类名的方式来指定过渡动画
    enter-class:"xx" 进去动画之前
    enter-active-class:"xx" 进去动画执行过程中
    enter-to-class:"xx" 进去动画完成之后
    leave-class:"xx" 离开动画之前
    leave-active-class:"xx" 离开动画执行过程中
    leave-to-class:"xx" 离开动画完成之后
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>自定义过渡类名xxx-class</title>
        <script src="js/vue.js"></script>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            #app{
                position: absolute;
                left: 50%;
                top: 50%;
                margin-left: -50px;
                margin-top: -50px;
            }
            .box{
                font-size: '1.4em';
                color: yellowgreen;
                margin-top: 20px;
            }
            .a{
                opacity: 0;
                transform-origin:left ;
            }
            .b{
                transition: all 3s;
            }
            .c{
                opacity: 1;
                font-size: '1em';
            }
            .d{
                opacity: 1;
                transform: translateX(15px) rotateZ(50deg);
            }
            .e{
                
                transition: all .6s;    
            }
            .f{
                opacity: 0;
                transform:rotateZ(45deg) translateY(30px) translateX(30px);
            }
            ,
        </style>
    </head>
    <body>
        <div id="app">
            <button type="button" @click="toggle">
                toggle
            </button>
            <transition appear
                enter-class="a"
                enter-active-class="b"
                enter-to-class="c"
                leave-class="d"
                leave-active-class="e"
                leave-to-class="f">
                <p class="box" v-if="isShow">Hello</p>
            </transition>
        </div>
        
        <script type="text/javascript">
            let vue = new Vue({
                el:"#app",
                data:{
                    isShow:true,
                },
                methods:{
                    toggle(){
                        this.isShow = !this.isShow;
                    }
                },
                computed:{}
            })
        </script>
    </body>
</html>

效果:打开界面一开始就显示Hello,点击按钮后Hello开始旋转并淡出
  • 利用第三方JavaScript动画库Velocity.js实现过渡动画
     1. 引入Velocity.js文件:
      <script src="js/velocity.js"></script>
    2.给指定的元素加上指定的动画样式名(Velocity.js和钩子函数搭配使用)
      v-on:before-enter="beforeEnter" 进去动画之前
      v-on:enter="enter" 进去动画执行过程中
      v-on:leave="leave" 离开动画执行过程中
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Velocity-js来实现过渡动画</title>
        <script src="js/vue.js"></script>
        <script src="js/velocity.js"></script>
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            #app{
                position: absolute;
                top: 50%;
                left: 50%;
                margin-left:-50px;
                margin-top:-50px;
            }
            .box{
                margin-top: 20px;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <button @click="toggle">toggle</button>
            <transition
                        v-on:before-enter="beforeEnter"
                        v-on:enter="enter"
                        v-on:leave="leave"
                        v-bind:css="false">
                <p class="box" v-if="isShow">Dome</p>
            </transition>
        </div>
        <script type="text/javascript">
            let vue =new Vue({
                el:"#app",
                data:{
                    isShow:false
                },
                methods:{
                    toggle(){
                        this.isShow = !this.isShow;
                    },
                    beforeEnter(el){
                        el.style.opacity = 0
                        el.style.transformOrigin = 'left'
                        Velocity(el, { opacity: 1, fontSize: '1.4em' });
                    },
                    enter(el,done){
                        Velocity(el, { fontSize: '1em' }, { duration: 300 }, { complete: done });
                    },
                    leave(el,done){
                        Velocity(el, { translateX: '15px', rotateZ: '50deg' }, { duration: 600 });
                        Velocity(el, { rotateZ: '100deg' }, { loop: 2 });
                        Velocity(el, {
                            rotateZ: '45deg',
                            translateY: '30px',
                            translateX: '30px',
                            opacity: 0
                        }, { complete: done });
                    },
                },
                computed:{}
            })
        </script>
    </body>
</html>

效果:点击按钮后Dome出现且开始字体大小缩放的动画,再次点击按钮后Dome开始做旋转且摇摆两下之后掉落淡出
  • 利用第三方CSS动画库Animate.css实现过渡动画
     1. 引入animate.css文件:
      <link rel="stylesheet" href="animate.min.css">
     2.给指定的元素加上指定的动画样式名(Animate.css配合自定义过渡类名使用)
      enter-active-class:"animated XXX"进去动画执行过程中
      leave-active-class:"animated XXX"离开动画执行过程中
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title>Animate.css实现过渡动画</title>
        <script src="js/vue.js"></script>
        <link href="https://cdn.jsdelivr.net/npm/animate.css@3.5.1" rel="stylesheet" type="text/css">
        <style type="text/css">
            *{
                margin: 0;
                padding: 0;
            }
            #app{
                position: absolute;
                left: 50%;
                top: 50%;
                margin-left: -50px;
                margin-top: -50px;
            }
            .box{
                margin-top: 20px;
                color: #DDA0DD;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <button @click="toggle">toggle</button>
            <transition
                    appear
                    enter-active-class="animated tada"
                    leave-active-class="animated bounceOutLeft">
                <p class="box" v-if="isShow">Hello</p>
            </transition>
        </div>
        <script type="text/javascript">
            let vue = new Vue({
                el:"#app",
                data:{
                    isShow:true
                },
                methods:{
                    toggle(){
                        this.isShow = !this.isShow;
                    }
                },
                computed:{}
            })
        </script>
    </body>
</html>

效果:打开界面一开始就显示Hello,点击按钮后Hello迅速向左淡出
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354