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

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">
单词:
  • directives 指令
  • inserted 已插入
  • binding 绑定
案例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>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容