二次封装组件vue

4--vue自定义指令 class.style绑定 动画

2020-03-18  本文已影响0人  Daeeman

1. directives-自定义指令

a.简介

除了核心功能默认内置的指令 (v-model 和 v-show),Vue 也允许注册自定义指令。注意,在 Vue2.0 中,代码复用和抽象的主要形式是组件。然而,有的情况下,你仍然需要对普通 DOM 元素进行底层操作,这时候就会用到自定义指令。举个聚焦输入框的例子,如下:

当页面加载时,该元素将获得焦点 (注意:autofocus 在移动版 Safari 上不工作)。事实上,只要你在打开这个页面后还没点击过任何内容,这个输入框就应当还是处于聚焦状态。现在让我们用指令来实现这个功能:

// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
  // 当被绑定的元素插入到 DOM 中时……
  inserted: function (el) {
    // 聚焦元素
    el.focus()
  }
})

如果想注册局部指令,组件中也接受一个 directives 的选项:

directives: {
  focus: {
      // 指令的定义
      inserted: function (el) {
      el.focus()
    }
  }
}

然后你可以在模板中任何元素上使用新的 v-focus 属性,如下:

<input v-focus>

b. 案例

directives ---- vue自定义指令
 作用
   1. 要操作dom时候
   2. 使用集成第三方插件时候
 定义:

        directives:{
            img:{
            inserted(el,binding){
           // el 当前指令所在的html节点
           // binding.value 指令的值
       }
    }
}
使用
    <div v-img="xxxxx">
单词:
案例1-自定义指令 v-img
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">   
    <title>自定义指令</title>
    <style>
        .box{width: 180px;height: 320px;}
    </style>
</head>
<body>    
<div id="app">   
    <div class="box" v-img="pics[0]"></div>
    <div class="box" v-img="pics[1]"></div>
    <div class="box" v-img="pics[2]"></div>
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
    el:"#app", 
    data:{pics:[
    "http://images.entgroup.cn/group2/M00/02/96/wKgAS13gt0WAS3CjAABoTRx_PZ8927.jpg",
    "http://images.entgroup.cn/group1/M00/05/2C/wKgASV34PqSAQliYAABmxNg1oI0829.jpg",
    "http://images.entgroup.cn/group2/M00/02/93/wKgAS12lOvCAP93oAACEwKNAR90206.jpg"]},  
    // 自定义指令 最大作用可以获取到自定义指令所在的 html 元素节点
    directives:{
        img:{
            // bind   update  inserted 当被插入到父节点
            inserted(el,binding){
                // el 自定义指令所再的元素
                // binding 绑定的数据  value 自定义指令的值
                let color = Math.floor(Math.random()*1000000);
                el.style.backgroundColor="#"+color;
                // 加载图片
                let img = new Image();
                // 创造一个新的图片;
                img.src = binding.value;
                console.log(el,binding);
                img.onload=function(){
                    el.style.backgroundImage=`url(${binding.value})`;
                    // 赋值背景图片
                }

            }
        }
    }
})    
</script>    
</body>
</html>

2. class绑定

a. 简介
  1. 属性绑定
    :class="'red blue'"
  2. 动态绑定
    :class="{'red':flag}"
    <div :class="isActive?'yellow':'red'">111</div>
    :class="{'active':index==current}"
  3. 数组绑定
    :class="['red','em','small']"
  4. 对象绑定
:class="classobj"
data:{
    classobj:{
        a:true,
        b:true
    }
}
b.案例 1:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">   
    <title>class绑定</title>
    <style>
        .red{color:red;}
        .em{font-style: italic;}
        .small{font-size:12px;}   
    </style>
</head>
<body>    
<div id="app">
    <!-- 在指令的值是js表达式不是字符串 -->
    <h1 :class="'red'">class是一个属性 可通过属性绑定</h1> 
    <h1 :class="{'red':flag}">class 对象方式绑定</h1>
    <h1 :class="['red','em','small']">数组的方法绑定多个</h1>
    <button @click="flag=!flag">{{flag}}</button>    
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
    el:"#app", 
    data:{
        flag:true,
        red:'red'
    }
})    
</script>    
</body>
</html>
class.png
c. 案例2-选项卡切换
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">   
    <title>选项卡案例</title>
    <style>
        .content{
            width: 300px;
            height: 300px;
            clear:both;
            border: 1px solid #ccc;
        }
        .title{
            display: inline-block;
            padding: 5px 15px;
            background-color: #ccc;
        }
        .active{color:#fff;background-color: dodgerblue;}
    </style>
</head>
<body>    
<div id="app">
    <div class="title" 
    v-for="(item,index) in list" 
    :key="index"
    @click="current=index"
    :class="{'active':index==current}"
     >{{item.title}}</div>
     <!-- 当单击标题 设置current为当前的index(单击改变current) -->
     <!-- 类名active 的绑定 如果当前current与index相等 就绑定activeclass -->
    <div class="content">{{list[current].content}}</div>
    <!-- 内容根据 current值不同来显示不同内容 -->
     
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
    el:"#app", 
    data:{
        list:[
            {title:"jquery",content:"jquery内容"},
            {title:"vue",content:"vue内容"},
            {title:"react",content:"react内容"},
        ],
        current:0,//默认显示第几个div
    }
})    
</script>    
</body>
</html>

3. style绑定

动态绑定

a.结构

style 绑定
对象

<h1 :style="{fontSize:'14px',color:'red'}">style的绑定</h1> 

<h1 :style="obj">对象变量方式</h1> 
data:{
   obj:{'font-size':"48px",fontStyle:'italic',color:red}
}
b. 案例
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">   
    <title>style绑定</title>
    <style>  </style>
</head>
<body>    
<div id="app">
    <h1 :style="{fontSize:'14px',color:'red'}">style的绑定</h1> 
    <div :style="'background:'+(isActive?'red':'yello')">动态三目写法</div> 
    <h1 :style="obj">对象变量方式</h1>   
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
    el:"#app", 
    data:{
        obj:{
            "font-size":"100px",
            fontStyle:'italic',
            color:'blue'
        }
    }
})    
</script>    
</body>
</html>

4. 综合案例--购物车

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">   
    <title>购物车案例</title>
 
</head>
<body>    
<div id="app">
   <table>
       <tr>
            <td >全选 <input type="checkbox" v-model="all" @change="checkAll"></td>
            <td>id</td>   <td>书名</td> <td>日期</td> <td>价格</td><td>数量</td>  <td>操作</td>
       </tr>
       <tr v-for="(item,index) in books" :key="index">
        <td><input type="checkbox" v-model="item.sel"></td>
        <td>{{item.id}}</td>
        <td>{{item.name}}</td>
        <td>{{item.date}}</td>
        <td>{{item.price}}</td>
        <td> 
            <button @click="item.num--">-</button>
            <input type="text" v-model.number="item.num">
            <button @click="item.num++">+</button>
        </td>
        <td> <button @click="delItem(item)">删除</button></td>
    </tr>
   </table> 
   总价格:{{total}}
</div>
<script src="./js/vue.js"></script>
<script>
new Vue({
    el:"#app", 
    data:{
        books:[
            {sel:true,id:1,name:"小红书",date:"2020/12/24",price:100,num:1},
            {sel:true,id:2,name:"小蓝书",date:"2020/12/25",price:20,num:1},
            {sel:true,id:3,name:"小绿书",date:"2020/12/26",price:80,num:1},
            {sel:true,id:4,name:"小白书",date:"2020/11/24",price:300,num:1},
            {sel:true,id:5,name:"vue精通",date:"2020/10/05",price:175,num:2}
        ],
        all:true,
    },
    computed:{
        "total":function(){
            var n=0;
            this.books.forEach(item=>{
                if(item.sel){
                    n+=item.price*item.num;
                    // 加上每项 单价*数量
                }              
            })
            return n;
            // 返回n;
        }
    },
    watch:{
      "books":{
          handler:function(nval){
              this.all = this.books.every(item=>item.sel);
            //   every 每一个都返回为true,则最终返回为true,有一个返回为false最终都返回为false
            //  当books有任何变化的时候都检测全选是否为true or false
          },
          deep:true
      }  
    },
    methods:{
        delItem(item){
            var re = window.confirm("你确定要删除么");
            if(re){
                let ind = this.books.indexOf(item);
                this.books.splice(ind,1);
            }
        },
        checkAll(){
            this.books.forEach(item=>item.sel=this.all);
            // 当全选按钮发生改变是 ,所有的books项目的sel值都等于 all的值
        }         
    }
})    
</script>    
</body>
</html>
购物车.png

5. Vue 动画

1.  vue它不能直接实现动画,它提供动画各阶段需要的class
2. <transition> 组件提供class
3. 在vue中,动画是在元素显示与隐藏的过程中,添加 class实现的
        v-if       v-else      v-show
4. transition组件提供

    v-enter-active     元素整个进入的过程
    v-enter              元素进入的初始状态
    v-enter-to          元素进入的结束状态
    v-leave-active      元素整个离开的过程
    v-leave               元素的离开初始状态
    v-leave-to          元素的离开结束状态


    自定义动画名
        enter-active-class=“xxx”
        leave-active-class=“xxx”
        要引入第三方css  animate.css

   动画模式 mode
        in-out    先执行进入动画,再执行离开动画
        out-in    先执行离开动画,再执行进入动画

5. transition-group组件
        tag            指定标签
        move-class     给正在移动中的元素添加class
        name           动画名称

    指定进入离开class
        enter-active-class
        leave-active-class       
案例 1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <script src="./js/vue.js"></script>
    <style>
        .fade-enter-active{ transition: all 2s ease;}
        /* 元素进入的整个过程 */
        .fade-leave-active{ transition: all .5s ease;}
        /* 元素离开的整个过程 */
        .fade-enter{opacity: 0;}
        /* 进入的初始状态 */
        .fade-enter-to{opacity: 1;}
        /* 进入的结束状态 */
        .fade-leave{opacity: 1;}
        /* 离开的初始状态 */
        .fade-leave-to{opacity: 0;}
        /* 离开的结束状态 */
    </style>
</head>
<body>
<div id="app">
    <button @click="flag=!flag">切换</button> <br>
    <transition name="fade">
        <img src="./img/sun.jpg" v-if="flag" alt="" width="120">
    </transition>
</div>
<script>
    new Vue({
        el:"#app",
        data:{flag:true}
    })
</script>
</body>
</html>
案例 2
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <script src="./js/vue.js"></script>
    <style>
        /* keyframes定义关键帧 fadeIn 动画名称 */
        @keyframes fadeIn {
            from{opacity: 0; transform:translate(-100px,0) rotate(-180deg)}
            /* 从{透明度:0,变换:位置变换(x位置-100,y位置0) 旋转变换(-180度)} */
            to{opacity: 1; transform:translate(0,0) rotate(0deg)}
        }
        @keyframes fadeOut {
            0%{opacity: 1;transform:translate(0,0) rotate(0deg)}
            100%{opacity: 0;transform:translate(100px,0) rotate(180deg)}
        }
        .fade-enter-active{ animation: fadeIn ease 1s; }
        /* 元素进入的整个过程 */
        .fade-leave-active{ animation: fadeOut ease 1s;}
        /* 元素离开的整个过程 */    
    </style>
</head>
<body>
<div id="app">
    <button @click="flag=!flag">切换</button> <br>
    <transition name="fade">
        <img src="./img/sun.jpg" v-if="flag" alt="" width="120">
    </transition>
    <!-- transition是vue内置的一个组件,只要是动画都要包裹再里面  深,动态给img 再离开和进入是添加6个不同的class -->
</div>
<script>
    new Vue({
        el:"#app",
        data:{flag:true}
    })
</script>
</body>
</html>

6. animate引入动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画</title>
    <link rel="stylesheet" href="./css/animate.min.css">
    <!-- 著名的css动画库引入 -->
    <script src="./js/vue.js"></script>
    <style>
       
    </style>
</head>
<body>
<div id="app">
    <button @click="flag=!flag">切换</button> <br>
    <transition enter-active-class="slideInDown animated" leave-active-class=" hinge animated">
        <img src="./img/sun.jpg" v-if="flag" alt="" width="120">
    </transition>
    <!-- 定义进入的动画名称  定义离开的动画名称 -->
    <!-- transition是vue内置的一个组件,只要是动画都要包裹再里面  深,动态给img 再离开和进入是添加6个不同的class -->
</div>
<script>
    new Vue({
        el:"#app",
        data:{flag:true}
    })
</script>
</body>
</html>

7. 动画模式

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>动画组</title>
    <link rel="stylesheet" href="./css/animate.min.css">  
    <script src="./js/vue.js"></script>
    <style>
        .fadeOutUp{ position: absolute;}
       .move{ transition: all ease .6s;}
    </style>
</head>
<body>
<div id="app">
    <input type="text" v-model="temp" placeholder="添加内容" 
    @keyup.enter="list.unshift(temp);temp=''">
    <transition-group tag="div" 
    enter-active-class="fadeInDown animated"
    leave-active-class="fadeOutUp animated"
    move-class="move"
    >
        <div v-for="(item,index) in list" :key="item">
            {{item}} <button @click="delItem(item)">x</button>
        </div>
    </transition-group>
   
     
</div>
<script>
    new Vue({
        el:"#app",
        data:{ 
            temp:"",
            list:['vue','react','angular']
        },
        methods:{
            delItem(item){
                var ind = this.list.indexOf(item);
                this.list.splice(ind,1)
            }
        }
    })
</script>
</body>
</html>
上一篇下一篇

猜你喜欢

热点阅读