Vue基础技能【六、自定义指令、过滤器、插槽、动画】

1、自定义指令

1.1、定义指令

  • 作用:帮助我们实现对于一些原生DOM的操作。比如说,页面一进入输入框就获取焦点;比如焦点离开输入框就开始验证。

  • 定义自定义指令:

    • 全局注册

      Vue.directive('指令名',{ 配置项 })
      // 全局注册要放在Vue实例化之前
      
    • 局部注册

      new  Vue({
         el:"",
         ...
         directives:{
            指令名:{
               配置项
            }
         }
      })
      

1.2、指令的配置项

  • 指令的生命周期钩子

  • bind 绑定 只触发一次

  • inserted 插入 只触发一次

  • update 更新 可能内部没更新完就触发了 反复触发

  • componentUpdated 内部的组件更新结束,本身也更新结束才触发 反复触发

  • unbind 解绑 只触发一次

  • 钩子函数的参数

    • el 指令所挂载的节点

    • binding 挂载的信息

      • binding.value 就是指令的值
      • binding.name 指令的名字, 没有v-
      • binding.expression 指令的表达式
    • vnode 虚拟节点

    • oldVnode 原来的虚拟节点

1.3、代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
       <h3 v-myhtml="'天下第一美男子'"></h3>
       <input type="text" v-focus>
    </div>
</body>
<script>
    // 全局注册、 局部注册
    // Vue.directive('指令名',{配置对象})

    // v-test
    Vue.directive('myhtml',{
        bind(el,binding){  // 绑定指令   触发一次
            console.log("bind");
        },
        inserted(el,binding){  // 节点插入的时候触发
            console.log('inserted');
            console.log(el);
            console.log(binding.value);
            el.innerHTML = '武哥'+binding.value
        },
        update(el,binding){  // 所在节点更新的时候触发,可能在子节点更新之前就被触发
            console.log('update');
        },
        componentUpdated(el,binding){  // 所在节点及子节点都更新完成之后才触发
            console.log('componentUpdated');
        },
        unbind(el,binding){
            console.log('unbind');
        }
    })

    new Vue({
        el:"#app",
        data:{
            nums:100
        },
        directives:{  // 局部注册
            focus:{
                inserted(el,binding){
                    el.focus();
                    console.log(el);
                    
                }
            }
        }
    })

</script>
</html>

2、过滤器

2.1、定义过滤器

  • 作用:对于需要展示的数据进行一定的处理;比如: 我们在展示价格数据的,需要保留两位小数,需要的英文单字首字母大写,这个时候我们就可以定义过滤器来进行处理。

  • 如何定义过滤器:

    • 全局注册

      Vue.filter('过滤器名',function(参数){
           // 一定要有 return
      })
      
    • 局部注册

      new Vue({
        el:"",
        ...
        filters:{
          过滤器名:function(参数){
            // 一定要有return 
          }
        }
      })
      

2.2、过滤器使用、传参

  • 简单实用

    {{  变量  |  过滤器名 }}
    
  • 多个过滤器一起使用

    {{  变量  |  过滤器名A  |  过滤器名B }}
    
  • 过滤器传参

    {{  变量  |  过滤器名A  |  过滤器名B(参数1,参数2) }}
    

2.3、代码实现

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
    <div id="app">
        {{ price.toFixed(2) }}
        <br>
        {{ price2.toFixed(1) }}
        <hr>
        {{ nums | toFix  }}
        <br>
        {{ price | toFix }}
        <br>
        {{ price2 | toFix(1) }}
        <br>
        {{ price3 | toFix(3) | addstr }}
        <br>
        {{ price3 | toFix(3) | addstr('过滤的结果是:') }}
    </div>    
</body>
<script>
    // 希望有一个可以对价格进行过滤的东西    过滤器

    // 全局注册,局部注册


    // 全局注册
    // console.log(Vue.filter);
    // 定义:Vue.filter('过滤器名',过滤器函数)  
                // 过滤器函数一定要有返回值
            /*
            Vue.filter('过滤器名',functon(变量值,传入的参数){
                // 过滤处理
                return  处理后的结果
            })
            */
    // 局部注册:

        /*
            new Vue({
                el:""
                ...,
                filters:{
                    过滤器名:function(变量值,传入的参数=参数默认值){
                        // 过滤处理
                         return  处理后的结果
                    }
                }
            })


        */        

    // 使用: {{ 变量 | 过滤器名 }}
    // 使用: {{ 变量 | 过滤器名(参数1,参数2) }}
    // 使用: {{ 变量 | 过滤器名1 | 过滤器名2 | 过滤器名3 |... }}
   
   
    Vue.filter('toFix',function(val,num=2){
        if(isNaN(val)){ // isNaN  是true  不是数字
            console.log('不是数字');
            return '不是数字';
        }
        return val.toFixed(num)
    })
    

    new Vue({
        el:"#app",
        data:{
            price:300.421,
            price2:400.246,
            price3:10.834539745,
            nums:'aaaa'
        },
        filters:{
            addstr:function(val,str='结果是:'){
                console.log(val);
                return str+val
            }
        }
    })


    // 函数的默认参数
    // function add(num){
    //     // var num = num || 20
    //     if(num){
    //         var num = num;
    //     }else{
    //         num = 20
    //     }
    //     console.log(num);
    // }
    // add();

    function add(num=20){
        console.log(num);
    }
    add();
    add(100)




</script>
</html>

3、插槽

  • 插槽是什么: 组件的标签之前放入一些html内容。那这些html内容被称为插槽。这些内容将会被渲染到组件的模板内部。

  • 插槽的作用:提供给了开发者自己去定义插槽内部的一些局部结构。

3.1、默认插槽

  • 组件调用时候

    <组件名>
    		html标签内容
    </组件名>
    
    <组件名>
    		<template v-slot:default>
          	html标签内容
        </template>
    </组件名>
    
  • 组件模板内部

    //组件的模板内
    
    <template>
    		<div>
    			<h3>我是组件模板</h3>
    			<slot></slot>   // 就可以将上面的html标签内容放在这里
    		</div>
    </template>
    
    
  • 代码实现:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <myalert>
                <h3>我是h3</h3>
                <p>2333333333</p>
            </myalert>
        </div>
    
        <template id="myalert">
            <div class="myalert">
                <slot></slot>
                我是myalert组件
            </div>
        </template>
    </body>
    <script>
        Vue.component('myalert',{
            template:"#myalert"
        })
    
        new Vue({
            el:"#app"
        })
    
        // 插槽的使用:     
                //  我们在组件运用的时候:   <myalert>标签内容</myalert>
                //  组件的模板里面:  使用slot标签获取上面的标签内容   <slot></slot>
    </script>
    </html>
    

3.2、具名插槽

  • 定义: 我们希望标签之间的HTML,不同的内容放在组件模板内部的不同地方。

  • 实现:

    • 组件调用的时候
    <组件名>
      <template v-slot:插槽名A>
      	HTML内容
      </template>
      <template v-slot:default>  // 默认插槽
      	HTML内容
      </template>
      <template v-slot:插槽名B>
      	HTML内容
      </template>
    </组件名>
    
    • 组件模板内部
    //组件的模板内
    
    <template>
    		<div>
    			<h3>我是组件模板</h3>
    			<slot name="default"></slot>   //   默认插槽
          <slot></slot>   //   默认插槽   可以省略 name
          <slot name="插槽名A"></slot>  
          <slot name="插槽名B"></slot>
    		</div>
    </template>
    
    
    
  • 代码实现

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <myalert>
                <h3>我是h3</h3>
                <p>2333333333</p>
    
                <template v-slot:aaa>
                    <h3>我是aaa的部分内容</h3>
                </template>
    
                <template v-slot:bbb>
                    <h3>我是bbb的部分内容</h3>
                </template>
    
            </myalert>
        </div>
    
    
    
        <template id="myalert">
            <div class="myalert">
                <slot name="default"></slot>
                我是myalert组件
                <slot name="aaa"></slot>
                <slot name="bbb"></slot>
            </div>
        </template>
    </body>
    <script>
        Vue.component('myalert',{
            template:"#myalert"
        })
    
        new Vue({
            el:"#app"
        })
    
    </script>
    </html>
    

3.3、作用域插槽

  • 目的:在插槽的内容html里面可以直接渲染父组件的变量 ,却无法直接渲染该组件自己的变量。作用域插槽就可以帮我们实现 在插槽内部 调用 组件里的数据

  • 实现:

    • 在组件调用的时候

      <组件名>
        <template v-slot:插槽名A="作用域变量"> // 作用域变量就是该插槽slot标签上面的所有属性
          {{ 作用域变量 }}     // 渲染出    { 属性名A:变量A,属性名B:变量B, }
        	HTML内容
        </template>
        <template v-slot:default>  // 默认插槽
        	HTML内容
        </template>
        <template v-slot:插槽名B>
        	HTML内容
        </template>
      </组件名>
      
    • 组件模板内部

      //组件的模板内
      
      <template>
      		<div>
      			<h3>我是组件模板</h3>
      			<slot name="default"></slot>   //   默认插槽
            <slot></slot>   //   默认插槽   可以省略 name
            <slot name="插槽名A" :属性名A="变量A"  :属性名B="变量B"></slot>  
            <slot name="插槽名B"></slot>
      		</div>
      </template>
      
      // 组件的JS内部
      {
        template:"",
        data(){
          return{
             变量A:值A,
             变量B:值B
          }
        }
      }
      
      
  • 代码实现:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <style>
            .box{
                width: 800px;
                background-color: #ccc;
                margin: 0 auto;
            }
            .header{
                height: 200px;
                background-color: red;
            }
            .main{
                height: 400px;
                border: 2px solid blue;
            }
            .footer{
                height: 100px;
                background-color: orange;
            }
        </style>
    </head>
    <body>
        <div id="app">
            <page>
                <template v-slot:tou="slotProps">
                    <h3>我是头部</h3>
                    {{slotProps}}
                    <p>
                        <a href="" v-for="(item,index) in slotProps.navdata" :key="index">{{item}}</a>
                    </p>
                </template>
                <template v-slot:default="defaultPorps">
                    <p>我是内容</p>
                    {{defaultPorps}}
                    <ul>
                        <li v-for="(item,index) in defaultPorps.list" :key="index">{{item}}</li>
                    </ul>
                </template>
                <template v-slot:jiao="slotProps">
                    <h3>我是脚步</h3>
                    {{slotProps}}
                    <p>{{slotProps.copy}}</p>
                </template>
            </page>
        </div>
        <!-- 页面内容模板 -->
        <template id="page">
           <div class="box">
                <div class="header">
                    <slot name="tou" :navdata="navdata"></slot>
                </div>
                <div class="main">
                    <slot :list="list"></slot>
                </div>
                <div class="footer">
                    <slot name="jiao" :copy="copy"></slot>
                </div>
           </div>
        </template>
    </body>
    <script>
    
        Vue.component('page',{
            template:"#page",
            data(){
                return{
                    navdata:['首页','关于我们','公司新闻','等等'],
                    list:['新闻1','新闻2','新闻3','新闻4'],
                    copy:"版权所有@翻版必究"
                }
            }
        })
    
        new Vue({
            el:"#app",
            data:{}
        })
    </script>
    </html>
    

3.4、旧语法

  • 为什么要学习旧语法: 因为很多一些成熟的UI框架,在封装的时候使用的是旧语法。比如element-ui

  • 区别:

    • 组件调用的时候

      <组件名>
        <template v-slot:插槽名A="作用域变量"> <!--新语法-->
        <template slot="插槽名A" slot-scope='作用域变量' > <!--旧语法-->
          {{ 作用域变量 }}     // 渲染出    { 属性名A:变量A,属性名B:变量B, }
        	HTML内容
        </template>
        <template v-slot:default>  // 默认插槽
        	HTML内容
        </template>
        <template v-slot:插槽名B>
        	HTML内容
        </template>
      </组件名>
      
    • 组件内部,和新语法一致。

  • 代码实现:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    </head>
    <body>
        <div id="app">
            <myalert>
                
                <!-- <template slot="default"> -->
                <template  slot-scope="props">
                     <h3>我是h3</h3>
                     <p>2333333333</p>
                     {{props}}
                </template>
    
                <!-- 新语法: v-slot:插槽名="插槽的作用域变量" -->
                <!-- <template v-slot:aaa> -->
                <!-- 旧语法: slot="插槽名"  slot-sope="插槽的作用域变量"  -->
                <template slot="aaa" slot-scope="myprops">
                    <h3>我是aaa的部分内容</h3>
                    {{ myprops }}
                </template>
    
                <!-- <template v-slot:bbb> -->
                <template slot="bbb">
                    <h3>我是bbb的部分内容</h3>
                </template>
    
            </myalert>
        </div>
    
    
    
        <template id="myalert">
            <div class="myalert">
                <slot name="default" yest="3234" yerrf="3333"></slot>
                我是myalert组件
                <slot name="aaa" :tttmsg="msg"></slot>
                <slot name="bbb"></slot>
            </div>
        </template>
    </body>
    <script>
        Vue.component('myalert',{
            template:"#myalert",
            data(){
                return{
                    msg:"1111111111"
                }
            }
        })
    
        new Vue({
            el:"#app"
        })
    
    </script>
    </html>
    

4、动画

4.1、动画状态

  • 进入

    • 进入前: v-enter
    • 进入中: v-enter-active
    • 进入后: v-enter-to
  • 离开

    • 离开前: v-leave

    • 离开中: v-leave-active

    • 离开后: v-leave-to

4.2、定义动画

  • 定义class

    .动画名-enter{ css样式 }  /*进入前*/
    .动画名-enter-active{ css样式 }  /*进入中    过渡。一般是transition  */
    .动画名-enter-to{ css样式 }  /*进入后*/
    .动画名-leave{ css样式 }  /*离开前*/
    .动画名-leave-active{ css样式 }  /*离开中  过渡。一般是transition   */
    .动画名-leave-to{ css样式 }  /*离开后*/
    
    /* 动画如果自然:  进入中和离开中是一样的内容 */
    
  • 使用动画

    <transition name="动画名">
    		<html内容>
    </transition>
    
  • 注意: 动画显示,你得实现html内容 显示 隐藏的切换

  • 代码实现:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
        <style>
            .over{
                width: 304px;
                height: 304px;
                margin: 0 auto;
                border: 4px solid #000000;
                overflow: hidden;
            }
            .box{
                width: 300px;
                height: 300px;
                border: 2px solid orange;
                position: relative;
                left: 0;
            }
            .myfade-enter{
                /* 进入的开始 */
                background-color: red;
                opacity: 0;
                position: relative;
                left: 500px;
            }
            .myfade-enter-active{  
                /* 进入过程中 */
                transition: all 1s ease-in;
            }
            /* .myfade-enter-to{ */
                /* 进入之后 */
                /* background-color: #fff; */
                /* opacity: 1; */
            /* } */
            /* .myfade-leave{
                background-color:#000;
            } */
            .myfade-leave-active{
                /* 离开过程中 */
                transition: all 1s ease-in;
            }
            .myfade-leave-to{
                /* 离开之后 */
                opacity: 0;
                background-color: red;
                position: relative;
                left: -500px;
            }
        </style>
    </head>
    <body>
        <div id="app">
            
            <button @clicK="state=!state">切换</button>
            <div class="over">
                <transition name="myfade">
                    <div class="box" v-if="state">
                        <h3>你好</h3>
                        <h3>你好</h3>
                        <h3>你好</h3>
                        <h3>你好</h3>
                        <h3>你好</h3>
                        <h3>你好</h3>
                    </div>
                </transition>
            </div>
        </div>
    </body>
    <script>
        // v-enter          进入的时候
        // v-enter-active   进入的过程中
        // v-enter-to       进入后 【舍弃】   其实就是v-leave
        // v-leave          离开之前
        // v-leave-active   离开过程
        // v-leave-to       离开后 【舍弃】   其实就是v-enter
    
        new Vue({
            el:"#app",
            data:{
                state:true
            }
        })
    
        // 动画组件:  <transition name="动画名称"></transition>
    
    
    </script>
    </html>
    

4.3、结合animate.css

  • 认识animate.css : 是一个css库,实现了很多动画效果

  • 传统使用:

    • 第1步:引入animate.css

    • 第2步: 给要用动画的标签 上面添加上 animated 和 动画名称 class

      <标签 class="animated bounceInDown"></标签>
      
    • 代码实现:

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <link rel="stylesheet" href="https://daneden.github.io/animate.css/animate.min.css">
          <style>
              .box{
                  width: 300px;
                  height: 300px;
                  background-color: red;
              }
          </style>
      </head>
      <body>
          
          <!-- 那个需要动画 加上  animated 的class  再添加上对应的动画class就好了-->
          <div class="box animated bounceInDown"></div>
      
      </body>
      </html>
      
  • 如何结合Vue实现效果

    • 第1步:引入animate.css

    • 第2步:给我们的transition标签添加上 enter-active-class 和 leave-active-class 属性。 每个的值就是animate里面的动画class.

       <transition  enter-active-class="animated bounceInLeft"  leave-active-class="animated bounceOutRight" >
          html内容
      </transition>
      
    • 代码实现:

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
          <link rel="stylesheet" href="https://daneden.github.io/animate.css/animate.min.css">
          <style>
              .over{
                  width: 304px;
                  height: 304px;
                  margin: 0 auto;
                  border: 4px solid #000000;
                  overflow: hidden;
              }
              .box{
                  width: 300px;
                  height: 300px;
                  border: 2px solid orange;
                  position: relative;
                  left: 0;
              }
          </style>
      </head>
      <body>
          <div id="app">
              
              <button @clicK="state=!state">切换</button>
              <div class="over">
                  <transition 
                      enter-active-class="animated bounceInLeft"
                      leave-active-class="animated bounceOutRight" 
                  >
                      <div class="box" v-if="state">
                          <h3>你好</h3>
                          <h3>你好</h3>
                          <h3>你好</h3>
                          <h3>你好</h3>
                          <h3>你好</h3>
                          <h3>你好</h3>
                      </div>
                  </transition>
              </div>
          </div>
      </body>
      <script>
        
          new Vue({
              el:"#app",
              data:{
                  state:true
              }
          })
      
          // 动画组件:  <transition name="动画名称"></transition>
      
      
      </script>
      </html>
      

发布了9 篇原创文章 · 获赞 0 · 访问量 96

猜你喜欢

转载自blog.csdn.net/qq_32620027/article/details/104379426