Vue组件+Vue动画

28 篇文章 0 订阅
19 篇文章 0 订阅

目录

Vue选项

自定义指令

过滤,管道filters  

全局组件

局部组件

props传递参数 

props细节

 组件传参父传子

组件传值总结

组件的插槽(嵌套)

具名插槽

弹框组件的使用http://t.csdn.cn/1Os9T

插槽的作用域

Vue动画

动画-过渡class

动画-使用关键帧动画

 动画-引入第三方

动画模式

动画列表过渡


Vue选项

el 模板
data 数据
methods方法
directives 指令
filters 过滤
watch 监听
computed 计算
props属性
created 创建完毕
template 模板
componets 组件

自定义指令

作用:操作dom;实例化第三方基于dom的插件

<input v-focus="true">

directives:{
    "focus":{
        update(el,binding){
             // el 指令所在节点
            // binding.value 指令的值
          }
      }
}

update, 更新就执行
bind 绑定一次
inserted 插入

过滤,管道filters  

作用:格式化数据

<body>
 
    <div id="app">
        <input type="text" v-model.lazy="day" placeholder="输入时间至今多久">
        <p>{{day|date}}</p>
    </div>
</body>
<script>
    new Vue({
        el: "#app",
        data(){
            return{
                day:""
            }
        },
        filters: {
            //val 是过滤前的值
            //return 过滤后的值
            date(val) {
                var time1 = new Date(val).getTime();
                var time2 = new Date().getTime();
                var dis = time2 - time1;
                if ((dis / 1000 > 0) && (dis / 1000) <= 60) {
                    return Math.floor(dis / 1000) + "秒前"
                } else if (dis / 1000 > 60 && dis / 1000 < 3600) {
                    return Math.floor(dis / 1000 / 60) + "分钟前";
                } else if (dis / 1000 > 3600 && dis / 1000 < (3600 * 24)) {
                    return Math.floor(dis / 1000 / 3600) + "小时前";
                } else if (dis / 1000 > (3600 * 24) && dis / 1000 < (3600 * 24 * 7)) {
                    return Math.floor(dis / 1000 / 3600 / 24) + "天前";
                } else if (dis / 1000 > 3600 * 24 * 7 && dis / 1000 < (3600 * 24 * 30)) {
                    return Math.floor(dis / 1000 / 3600 / 24 / 7) + "周前";
                } else if (dis / 1000 > (3600 * 24 * 30) && dis / 1000 < (3600 * 24 * 30 * 12)) {
                    return Math.floor(dis / 1000 / 3600 / 24 / 30) + "月前";
                } else if (dis / 1000 > 3600 * 24 * 30 * 12) {
                    return Math.floor(dis / 1000 / 3600 / 24 / 30 / 12) + "年前";
                }
 
            }
        }
    })
</script>
 
</html>

全局组件

Vue.component 来创建组件:

 Vue.component("btn",{
    template:`<button @click="n++">{{n}}</button>`,
    data(){return {n:1}}
})

局部组件

1.定义组件
const step = {
    template:`<div><button @click="n--">-</button>{{n}}<button @click="n++">+</button></div>`,
    data(){return {n:1}}

}

2.注册组件
const app = new Vue({    
    components:{step}
})
3.使用组件
<step></step>
<step></step>

<body>
    <div id="app">
        <!-- 03 使用组件 -->
        <step></step> <br>
        <step></step> <br>

    </div>
    <script>
        // 01 定义组件
        var step = {
            template: `<span>
                <button @click="count--" :disabled="count<=1">-</button>
                <input type="text" v-model="count">
                <button @click="count++" :disabled="count>=999">+</button>
                <span>`,

            data() {
                return {
                    count: 1,
                }
            }
        }
        new Vue({
            el: "#app",
            //02 注册组件
            components: { step },

        })

    </script>

props传递参数 

传递
<step :num="10"></step>
<step :num="5"></step>

接收
props:{
    "num":{type:Number,default:1}
},

使用
data(){return {n:this.num}}


对象与数组的默认值必须是函数的返回值

props细节

    1.每一个数据项,都可以有3个属性进行约束type,类型约束,约束父组件给子组件传递的数据类型,类型可以是:Object、Array、Number、String、Boolean等几种。
    2.default,指定默认值,如果父组件没有传递数据,可以指定默认值
    3.required,指定该数据项是否必须传递

 组件传参父传子

<body>
    <div id="app">
        <!-- 03 使用组件 -->
        <h1>组件传参</h1>
        <p>父传子</p>
        <step v-model="r"></step> <br>
        <step :value="r" @input="r=$event" :min="100" :max="500" :step="10"></step> <br>
        <input type="range" min="100" max="500" v-model.number="r">
        <div :style="{border:'2px solid red',borderRadius:r+'px',width:r+'px',height:r+'px'}"></div>

    </div>
    <script>
        // 01 定义组件
        new Vue({
            el: "#app",
            //02 注册组件
            components: { step },
            data() {
                return {
                    r: 100,
                }
            }

        })

    </script>

js

// 01 定义组件
var step = {
	template: `<span>
			<button @click="count-=step" :disabled="count<=min">-</button>
			<input type="text" v-model.lazy.number="count"/>
			<button @click="count+=step"  :disabled="count>=max">+</button>
			</span>`,
	props:{  //props接收父组件传递过来的参数
		value:{ //参数名称value
			type:Number, //参数数据类型是number
			default:1 //默认值是1,如果不传value的值是1
		},
		// 接收父组件传递过来参数最小,最大值,步进值
		min:{
			type:Number,
			default:1
		},
		max:{
			type:Number,
			default:999
		},
		step:{
			type:Number,
			default:1
		}
	},
	data() {
		return {
			count: this.value//count的默认值是父组件传过来的参数value
		}
	},
	watch:{
		count:{
			handler(){
				// 限定最大值,最小值
				if(this.count>=this.max){this.count=this.max};
				if(this.count<=this.min){this.count= this.min}
				// 子传父 通过emit发送事件
				this.$emit("input",this.count);
			},
			deep:true,
		},
		value:{
			handler(){
				// 监听value值的变化更新count(可选)
				this.count = this.value;
			},
			deep:true
		}
	}
}

// 为什么不直使用this.value 和input框绑定
// 答:父组件传到子组件的参数必须是只读
// 当count的数据发生变化的时候通知父组件更新数据

1、父组件定义数据 2、父组件通过属性的方式给子组件传递数据 3、子组件通过props属性接受数据并做参数设置 4、子组件使用传递过来的数据 

组件传值总结

<body>
    <!--
       a.父组件向子组件传值:通过v-bind:的形式进行数据的传递(可直接简写为冒号)
                然后子组件 使用props来接收
       b.子组件向父组件传值:
            局部组件TodoItem的li有handleItemClick事件
            this.$emit("delete",this.index):子组件向外触发事件,并携带参数
            父组件中 @delete="handleItemDelete" 监听到删除事件,
            于是调用handleItemDelete:function(index)方法            
    -->
    <div id="root">
        <div>
            <input type="text" v-model="inputValue">
            <button v-on:click="handleBtnClick">提交</button>
        </div>
        <ul>
            <!--<li v-for="item in list">{{item}}</li>-->

              <!--父组件(最外层的Vue实例)中data里面的list 传给子组件
                        子组件遍历list,得到item,然后给了子组件的一个变量content
                   创建这个子组件todo-item的同时,也监听到子组件的delete事件
                    index指的是是第几个todo-item
                    向子组件传值:不仅传content,还把对应的下标传下去
            -->
            <todo-item v-bind:content="item"
                       v-bind:index="index"
                       v-for="(item,index) in list"
                       @delete="handleItemDelete">  <!--父组件监听delete事件 去执行handleItemDelete方法-->

            </todo-item>
        </ul>

    </div>

    <script>

        //2.局部组件   同样,子组件要是想用index,就必须接收index
        var TodoItem ={
            props:['content','index'],
            template:"<li @click='handleItemClick'>{{content}}</li>",
            methods:{
                handleItemClick:function () {//子组件一旦被点击 不但触发delete事件,同时还把this.index作为参数 带给父组件
                    this.$emit("delete",this.index); //子组件向外触发事件  index传给父组件
                }
            }
        }

        var app=new Vue({
            el:'#root',

            //2.注册局部组件 到 Vue实例中
            components:{
              TodoItem:TodoItem
            },

            data:{
               list: [],
                inputValue:''
            },
            methods:{
                handleBtnClick:function () {
                    this.list.push(this.inputValue)
                    this.inputValue='';
                },

                handleItemDelete:function(index){
                    alert(index);
                    this.list.splice(index,1);//从哪个位置删除1个元素
                }
            }
        });

    </script>
</body>

组件的插槽(嵌套)

使用 <slot> 作为我们想要插入内容的占位符
<step>
     你好,我是嵌套内容
</step>
 template:`<div><h1>组件的标题</h1><slot></slot></div>`

具名插槽

<body>
    <div id="app">
      <div slot="header">我是头部内容</div>
      <div slot="main">我是主体内容</div>
      <div slot="footer">我是底部内容</div>
    </div>
  </body>
 
  <script>
    var mySon = {
      data: function() {
        return {};
      },
      template: `
      <div>
          <div><slot name='header'></slot></div>
          <div><slot name='main'></slot></div>
          <div><slot name='footer'></slot></div>
      </div>
      
      `,
      methods: {}
    };
 
    var vue = new Vue({
      el: "#app",
      data: {},
      methods: {},
      components: {
        "my-son": mySon
      }
    });
  </script>

弹框组件的使用http://t.csdn.cn/1Os9T

插槽的作用域

<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<body>
    <div id="app">
        <h1>插槽的作用域(父组件自定义渲染子组件局部内容)</h1>
        <!-- 使用组件 -->
        <lis :list="list">
            <template v-slot:default="scope">
                <span>{{scope.item}}</span>
            </template>
        </lis>
    </div>
    <script>
        //定义组件
        var lis = {
            template: `
            <div>
            <div v-for="item in list" :key="item">
                <slot :item="item"></slot>
            </div>
        </div>
            `,
            props: {
                list: {
                    type: Array
                }
            }
        }
        new Vue({
            el: "#app",
            //注册组件
            components: {
                lis,
            },
            data() {
                return {
                    list: ["Vue", "React", "Angular"]
                }
            }
        })

    </script>

Vue动画

动画-过渡class

在进入/离开的过渡中,会有 6 个 class 切换。

v-enter-active 进入开始 v-enter-to 进入结束  v-enter-active进入整个状态 v-leave-active 离开开始  v-leave-to 离开结束   v-leave-active离开整个状态

<style>
    .fade-enter-active {
        /* 进入的整个状态 */
        transition: all ease 1s;
    }

    .fade-enter {
        /* 进入初始状态 */
        opacity: 0;
        transform: rotate(-180deg);
    }

    .fade-enter-to {
        /* 进入最终状态 */
        opacity: 1;
        transform: rotate(0deg);
    }

    .fade-leave-active {
        /* 离开整个状态 */
        transition: all ease 1s;
    }

    .fade-leave {
        opacity: 1;
        transform: rotate(0deg);
    }

    .fade-leave-to {
        opacity: 0;
        transform: rotate(180deg);
    }
</style>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<body>
    <div id="app">
        <h1>动画</h1>
        <button @click="flag =!flag">切换</button>
        <p>
            <transition name="fade">
                <img src="./img/sun1.jpg" alt="" v-if="flag" width="100">
            </transition>

        </p>

    </div>
    <script>
        new Vue({
            el: "#app",
            data() {
                return {
                    flag: true
                }
            }
        })


    </script>

动画-使用关键帧动画

<style>
    @keyframes fadein {
        from {
            opacity: 0;
            transform: scale(0);
        }

        to {
            opacity: 1;
            transform: scale(1);
        }
    }

    @keyframes fadeout {
        0% {
            opacity: 1;
            transform: scale(1);
        }

        100% {
            opacity: 0;
            transform: scale(0);
        }
    }

    .fade-enter-active {
        /* 进入的整个状态,执行一个关键帧动画 */
        animation: fadein ease 1s;
    }

    .fade-leave-active {
        /* 离开整个状态,执行一个关键帧动画 */
        animation: fadeout ease 1s;
    }
</style>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<body>
    <div id="app">
        <h1>动画</h1>
        <button @click="flag =!flag">切换</button>
        <p>
            <transition name="fade">
                <img src="./img/sun1.jpg" alt="" v-if="flag" width="100">
          </transition>
        </p>
    </div>
    <script>
        new Vue({
            el: "#app",
            data() {
                return {
                    flag: true
                }
            }
        })

    </script>

 动画-引入第三方

animate动画库:https://www.jq22.com/yanshi819

<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="./css/animate.min.css">
    <title></title>
</head>
<style>

</style>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>

<body>
    <div id="app">
        <h1>动画</h1>
        <button @click="flag =!flag">切换</button>
        <p>
            <transition name="fade" enter-active-class="flipInX animated" leave-active-class="hinge animated">
                <img src="./img/sun1.jpg" alt="" v-if="flag" width="100">
            </transition>

        </p>

    </div>
    <script>
        new Vue({
            el: "#app",
            data() {
                return {
                    flag: true
                }
            }
        })
    </script>

动画模式

in-out 先进在出,out-in先出在进

<transition  mode="out-in" enter-active-class="animated slideInLeft" leave-active-class="slideOutRight animated">
    <button
key='a' v-if="flag">A</button>
    <button
key='b' v-else>B</button>
</transition>   

动画列表过渡

我们会使用 <transition-group> 组件实现列表过渡
<transition-group tag="div" name="slide"  >
     <div class="item" v-for="item in undoList" :key="item.name">
.....

</transition-group>

.slide-leave-active{
    animation: slideOut ease 1s;

    position: absolute;
}
/* transition-group 正在移动中的类名 */
/* 移动中的元素 */
.slide-move{
    transition: all ease 1s;
}

<transition-group tag="div" enter-active-class="fadeIn animated" leave-active-class="fadeOut animated">
    >
    <img v-show="current ===index" v-for="(item,index) in count" :key="item" :src="item" width="100%" >
    </transition-group>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值