专栏首页魏晓蕾的专栏【Vue.js】Vue.js中的事件处理、过滤器、过渡和动画、组件的生命周期及组件之间的通信

【Vue.js】Vue.js中的事件处理、过滤器、过渡和动画、组件的生命周期及组件之间的通信

1、事件处理

事件绑定监听

  • v-on:xxx=“func”
  • @xxx=“func”
  • @xxx=“func(参数)”

参数

  • 默认事件形参:event
  • 隐含属性对象:event(在原生事件中,event是事件对象,在自定义事件中,

事件修饰符

  • .prevent:阻止事件的默认行为 event.preventDefault()
  • .stop:停止事件冒泡 event.stopPropagation()

按键修饰符

  • .keycode:操作的是某个keycode值的键
  • .enter:操作的是enter键
  • .tab:操作的是tab键
  • .delete:操作的是“删除”和“退格”键
  • .esc:操作的是ESC键
  • .space:操作的是空格键
  • .up:键抬起
  • .down:键按下
  • .left:操作的是左箭头
  • .right:操作是是右箭头

示例代码

## DealEvents.vue

<template>
    <div>
        <button @click="clickBtn('撩课', $event)">点我</button>

        <h3>事件修饰符</h3>
        <a href="http://www.itlike.com" @click.prevent="aClick">撩课</a>
        <div style="width: 100px; height: 100px; background-color:red;" @click="divClick">
            <button @click.stop="btnClick">点我</button>
        </div>

        <h3>按键修饰符</h3>
        <input type="text" @keyup.enter="dealKey">
    </div>
</template>

<script>
    export default {
        name: "DealEvents",
        methods:{
            clickBtn(args, event){
                console.log(args);
                console.log(event);
            },

            aClick(){
                alert(0);
            },

            btnClick(){
                alert('点击了里面的按钮');
            },

            divClick(){
                alert('点击了父标签');
            },

            dealKey(event){
                console.log(event['keyCode']);
            }
        }
    }
</script>

<style scoped>

</style>
## App.vue

<template>
    <div id="app">
        <DealEvents />        
    </div>
</template>

<script>
    import DealEvents from './components/DealEvents'

    export default {
        name: 'app',
        components: {
            DealEvents
        }
    }
</script>

<style>

</style>

2、过滤器

概念

  • 对要显示的数据进行特定格式化后再显示
  • 并没有改变原本的数据, 而是产生新的对应的数据

定义过滤器

  • 全局定义
// 注册全局过滤器
Vue.filter('totalMonetFormat', (value)=>{
   return '¥' + Number(value).toFixed(3);
});
  • 局部定义
filters: {
   moneyFormat(value) {
       return '¥' + Number(value).toFixed(2);
   },
   timeFormat(value, format='YYYY-MM-DD HH:mm:ss'){
       return moment(value).format(format);
   }
}

使用过滤器

<template>
    <div>
        <h3>格式化人民币</h3>
        <p>局部过滤:{{money | moneyFormat}}</p>
        <p>局部过滤:{{page | moneyFormat}}</p>
        <p>全局过滤:{{money | totalMonetFormat}}</p>
        <p>全局过滤:{{page | totalMonetFormat}}</p>
        <p>------------------------------------------------</p>
        <h3>格式化日期</h3>
        <p>{{time | timeFormat}}</p>
        <p>{{time | timeFormat('YYYY-MM-DD')}}</p>
        <p>{{time | timeFormat('HH:mm:ss')}}</p>
    </div>
</template>

示例代码

## main.js

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false;

// 注册全局过滤器
Vue.filter('wholeMoneyFormat', (value)=>{
	return '¥' + Number(value).toFixed(4);
});

new Vue({
	render: h => h(App),
}).$mount('#app');
## LkFilters.vue

<template>
    <div>
        <h3>格式化人民币</h3>
        <p>{{money | moneyFormat}}</p>
        <p>{{page | moneyFormat}}</p>
        <p>---------------------------------------------</p>
        <p>{{money | wholeMoneyFormat}}</p>
        <p>{{page | wholeMoneyFormat}}</p>
        <h3>格式化日期</h3>
        <p>{{time | timeFormat}}</p>
        <p>{{time | timeFormat('YYYY-MM-DD')}}</p>
        <p>{{time | timeFormat('HH:mm:ss')}}</p>
    </div>
</template>

<script>
    import moment from 'moment'
    export default {
        name: "LkFilters",
        data(){
            return {
                money: 22345,
                page: 189.4345,
                time: new Date()
            }
        },
        mounted(){
            setInterval(()=>{
                this.time = new Date()
            }, 1000)
        },
        // 局部过滤器
        filters: {
            moneyFormat(value){
                return '¥' + Number(value).toFixed(2);
            },
            timeFormat(value, format='YYYY-MM-DD HH:mm:ss'){
                return moment(value).format(format);
            }
        }
    }
</script>

<style scoped>

</style>
## App.vue

<template>
    <div id="app">
        <LkFilters />
    </div>
</template>

<script>
    import LkFilters from './components/LkFilters'
    
    export default {
        name: 'app',
        components: {
            LkFilters
        }
    }
</script>

<style>

</style>

3、过渡和动画

概念

  • vue通过操作 css 的 trasition 或 animation可以给特定的目标元素添加/移除特定的 class

过渡的相关类名

  • xxx-enter/xxx-leave-to:指定隐藏时的样式
  • xxx-enter-active: 指定显示的 transition
  • xxx-leave-active: 指定隐藏的 transition

操作步骤

  • 在目标元素外包裹<transition name="xxx">
  • 定义class样式:指定过渡样式(transition),指定隐藏时的样式(opacity/其它)

示例代码

## TransitionAndAnimate.vue

<template>
    <div>
        <button @click="show = !show">切换</button>
        <transition name="fade">
            <div class="box" v-if="show">撩课学院</div>
        </transition>
    </div>
</template>

<script>
    export default {
        name: "TransitionAndAnimate",
        data(){
            return {
                show: false
            }
        }
    }
</script>

<style scoped>
    .box{
        width: 200px;
        height: 200px;
        background-color: red;
        color: #fff;
        font-size: 20px;
        display: flex;
        justify-content: center;
        align-items: center;
    }

    .fade-enter, .fade-leave-to{
        opacity: 0;
        transform: translateX(200px) scale(3);
    }

    .fade-enter-active, .fade-leave-active{
        transition: all 2s ease-in-out;
    }
</style>
## TransitionAndAnimateTwo.vue

<template>
    <div>
        <button @click="flag = !flag">切换</button>
        <p></p>
        <transition name="bounce">
            <img v-if="flag" :src="pic" alt="">
        </transition>
    </div>
</template>

<script>
    import pic from '@/assets/img_02.jpg'

    export default {
        name: "TransitionAndAnimateTwo",
        data() {
            return {
                pic: pic,
                flag: false
            }
        }
    }
</script>

<style scoped>
    .bounce-enter-active {
         animation: bounce 1s;
    }

    .bounce-leave-active {
        animation: bounce 1s reverse;
    }

    @keyframes bounce {
        0% {
            transform: scale(0);
        }
        25% {
            transform: scale(0.2);
        }
        50% {
            transform: scale(0.4);
        }
        75% {
            transform: scale(0.6);
        }
        100% {
            transform: scale(1);
        }
    }
</style>
## TransitionAndAnimateThree.vue

<template>
    <div>
        <button @click="flag = !flag">切换</button>
        <p></p>
        <transition
            enter-active-class="animated rollIn"
            leave-active-class="animated rollOut"
            :duration="{ enter: 1000, leave: 500 }"
        >
            <img v-if="flag" :src="pic" alt="">
        </transition>
    </div>
</template>

<script>
    import pic from '@/assets/img_02.jpg'
    import animate from 'animate.css'

    export default {
        name: "TransitionAndAnimateThree",
        data() {
            return {
                pic: pic,
                flag: false
            }
        }
    }
</script>

<style scoped>

</style>
## App.vue

<template>
    <div id="app">
        <TransitionAndAnimate />
        <TransitionAndAnimateTwo />
        <TransitionAndAnimateThree />
    </div>
</template>

<script>
    import TransitionAndAnimate from './components/TransitionAndAnimate'
    import TransitionAndAnimateTwo from './components/TransitionAndAnimateTwo'
    import TransitionAndAnimateThree from './components/TransitionAndAnimateThree'

    export default {
        name: 'app',
        components: {
            TransitionAndAnimate,
            TransitionAndAnimateTwo,
            TransitionAndAnimateThree
        }
    }
</script>

<style>

</style>

4、组件的生命周期

生命周期图示

钩子函数

  • 初始化显示
  1. beforeCreate()
  2. created()
  3. beforeMount()
  4. mounted()
  • 更新状态
  1. beforeUpdate()
  2. updated()
  • 销毁 vue 实例
  1. beforeDestory()
  2. destoryed()

常用的生命周期方法

  • created()/mounted():发送ajax请求,启动定时器等异步任务
  • beforeDestory():收尾操作,比如: 清除定时器、数据缓存

示例代码

## LifeCycle.vue

<template>
    <div>
        <p v-if="isShow">{{str1}}</p>
        <p v-else>{{str2}}</p>
        <button @click="destory">销毁</button>
    </div>
</template>

<script>
    export default {
        name: "LifeCycle",

        beforeCreate(){
             console.log('1:beforeCreate()');
        },

        data(){
            return {
                isShow: false,
                str1: '撩课学院',
                str2: 'itLike.com'
            }
        },
        
        methods:{
            destory(){
                this.$destroy();
            }
        },

        created() {
            console.log('2:created()');
        },
        beforeMount() {
            console.log('3:beforeMount()');
        },
        mounted() {
            console.log('4:mounted()');
            // 定时器
            this.intervalId = setInterval(()=>{
                console.log('+++++++++++---++++++++++');
                this.isShow = !this.isShow;
            }, 1000);
        },
        beforeUpdate() {
            console.log('5:beforeUpdate()');
        },
        updated() {
            console.log('6:updated()');
        },

        beforeDestroy() {
            console.log('7:beforeDestroy()');
            // 清除定时器
            clearInterval(this.intervalId);
        },
        destroyed() {
            console.log('8:destroyed()');
        }
    }
</script>

<style scoped>

</style>
## App.vue

<template>
    <div id="app">
        <LifeCycle />
    </div>
</template>

<script>
    import LifeCycle from './components/LifeCircle'

    export default {
        name: 'app',
        components: {
            LifeCycle
        }
    }
</script>

<style>

</style>

5、组件之间的通信

通信基本原则

  • 不要在子组件中直接修改父组件的状态数据
  • 数据和处理数据的函数应该在同一模块内

组件通信常用方式

  • props
  • 自定义事件
  • 消息订阅与发布
  • vuex

组件通信方式1:props

  • 在组件内声明所有的 props:
  1. 只指定名称:
props: ['name', 'age', 'logDog']
  1. 指定名称和类型
props: {
    name: String,
    age: Number,
    logDog: Function
}
  1. 指定名称、类型、必要性、默认值
props: {
    name: {type: String, required: true, default:xxx},
}
  • 使用注意
  1. 此方式用于父组件向子组件传递数据
  2. 所有标签属性都会成为组件对象的属性,模板页面可以直接引用
  3. 存在缺陷: (1)如果需要向非子后代传递数据必须多层逐层传递 (2)兄弟组件间也不能直接 props 通信, 必须借助父组件才可以

代码示例

## PropsComponent.vue

<template>
    <div>
        <h4>姓名:{{name}}</h4>
        <h4>年龄:{{age}}</h4>
        <p>{{person}}</p>

        <button @click="logPerson('大撩撩', 60)">调用方法</button>
    </div>
</template>

<script>
    export default {
        name: "PropsComponent",
        // props: ['name', 'age']
        /*
        props: {
            name: String,
            age: Number,
            person: Object,
            logPerson: Function
        }
        */
        props: {
            name: {type: String, required: true, default: '撩课'},
            age:  {type: Number, required: true, default: 20},
            person: Object,
            logPerson: Function
        }
    }
</script>

<style scoped>

</style>
App.vue

<template>
    <div id="app">
         <PropsComponent :age=25 :person="p" :log-person="logPerson" />
    </div>
</template>

<script>
    import PropsComponent from './components/PropsComponent'

    export default {
        name: 'app',
        data(){
           return {
               p: {
                   name: '张三丰',
                   age: 600
               }
           }
        },
        components: {
            PropsComponent
        },
        methods: {
            logPerson(name, age){
                alert(`姓名:${name}, 年龄:${age}`);
            }
        }
    }
</script>

<style>
    .word{
        width: 300px;
        height: 200px;
        background-color: red;
        color: #fff;
        display: flex;
        justify-content: center;
        align-items: center;
    }
</style>

组件通信方式2:自定义事件

  • 绑定事件监听:
  <button @click="btnClick">删除父标签P</button>
  
  this.$emit('btnClick', {name: '小撩', age: 25, sex:'女'});
  • 触发事件:
<CustomEvents @btnClick="deleteP"/>

 deleteP(args){
      console.log(args);
      this.$refs.word.remove();
  }
  • 指定名称、类型、必要性、默认值:
props: {
    name: {type: String, required: true, default:xxx},
}
  • 使用注意
  1. 此方式只用于子组件向父组件发送消息或数据
  2. 隔代组件或兄弟组件间通信此种方式不合适

代码示例

## CustomEvents.vue

<template>
    <div>
        <button @click="btnClick">删除父组件的P标签</button>
    </div>
</template>

<script>
    export default {
        name: "CustomEvents",
        methods: {
            btnClick(){
                // 告诉父组件,我点击了按钮
                this.$emit('btnClick', {name: '哈哈哈', sex:'男'});
            }
        }
    }
</script>

<style scoped>

</style>
## App.vue

<template>
    <div id="app">
         <CustomEvents @btnClick="deleteP"/>
         <p ref="word" class="word">我是即将被删除的</p>
    </div>
</template>

<script>
    import CustomEvents from './components/CustomEvents'

    export default {
        name: 'app',
        data(){
           return {
           }
        },
        components: {
            CustomEvents
        },
        methods: {
            deleteP(args){
                console.log(args);
                this.$refs.word.remove();
            }
        }
    }
</script>

<style>
    .word{
        width: 300px;
        height: 200px;
        background-color: red;
        color: #fff;
        display: flex;
        justify-content: center;
        align-items: center;
    }
</style>

组件通信方式3:PubSub 发布订阅

  • 安装:
>> npm install --save pubsub-js
  • 引入:
import PubSub from ‘pubsub-js’
  • 界面操作:
// 发布删除P标签消息
PubSub.publish("delete-p", {name:"大撩撩", sex:"女", age: 45});

// 订阅关闭弹窗事件,参数event指"delete-p"
PubSub.subscribe("delete-p", (event, data) => {
   console.log(data);
   // 删除P标签
   this.deleteP();
 });
  • 此方式可实现任意关系的组件间通信,交换数据

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 【Vue.js】Vue.js基本语法

    魏晓蕾
  • 【Spark】Spark SQL原理、编译、配置及运行方式详述

    (1)在Hadoop中运行SQL的工具 在Hadoop中运行SQL的工具有Hive、Impala、Apache Drill、Presto、Spark SQL等...

    魏晓蕾
  • 【Oozie】Oozie中工作流workflow的定义及各种Action的配置运行

    版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/...

    魏晓蕾
  • 为什么我认为数据结构与算法对前端开发很重要?

    一个具有层级结构的数据,实现这个功能非常容易,因为这个结构和组件的结构是一致的,递归遍历就可以了。

    疯狂的技术宅
  • python dict乱码如何解决

    问题: Python中的列表(list)或字典包含中文字符串,直接使用print会出现以下的结果:

    砸漏
  • Spring Aop之Cglib实现原理详解

    Spring Aop实现对目标对象的代理,主要有两种方式:Jdk代理和Cglib代理。这两种代理的区别在于,Jdk代理与目标类都会实现同一个接口,并且在代理...

    田维常
  • float到底是干什么的?

    划重点 float的真正用途不是我们平时用于将同模块下的元素并行显示,也不是为了实现将元素放在某一特殊位置时使用! float正真的作用是!各位老爷可以...

    星尘的一个朋友
  • MySQL中需要重视的隐式转换

    在系统集成,对接的过程中,很多时候我们都会忽略数据类型的兼容性,导致在系统运转起来的时候,原本正常的流程会容易堵塞,其中一个潜在的原因就是因为数据隐式转换带来的...

    jeanron100
  • vue从列表页到详情页的面包屑处理方法

    DataAccountDay组件里面是一个列表,点击列表进入detail.vue页面

    tianyawhl
  • Vue 中「自定义指令」的魅力

    但是内置指令,在实际的开发过程中可能这些并不能满足所有的需求。所以 Vue 给我们提供来一个灵活的方法「自定义指令」。

    六小登登

扫码关注云+社区

领取腾讯云代金券