Vue2(十):全局事件总线、消息订阅与发布、TodoList的编辑功能、$nextTick、动画

本文介绍了如何在Vue应用中使用全局事件总线进行组件间通信,包括Vue原型上的自定义事件、Vuex的替代方案,以及消息订阅发布模式。同时讲解了Vue的$nextTick和动画功能,以及如何使用transition和transition-group实现元素的动态进出效果。
摘要由CSDN通过智能技术生成

一、全局事件总线!!

任意组件间通信

比如a想收到别的组件的数据,那么就在a里面给x绑定一个demo自定义事件,所以a里面就得有一个回调函数吧,然后我要是想让d组件给a穿数据,那就让d去触发x的自定义事件,并且传参数进去,那么触发自定义事件就也会调用回调函数,就把数据给到a了 

1.安装全局事件总线

那么x应该放到哪里呢?之前学prototype的时候说它可以让vc、vm都能找到,x放在vue的原型对象上,x写到main.js中

new Vue({
	el:'#app',
	render: h => h(App),
	beforeCreate() {
		Vue.prototype.$bus=this
	},
})

注意$on、$off只有vm、vc才能用,如果把创建为一个新的vc可以实现,但是代码有点多,我们就把它创建成一个vm,有一个现成的vm让x直接等于它,写在new Vue后边呢在模版解析完之后才能赋值太晚了,所以就用钩子来赋值。(x一般写成$bus)

2.使用事件总线

a组件要绑定自定义事件

mounted(){
			this.$bus.$on('hello',(data)=>{
				console.log('我是school,我收到了',data)
			})
		}

3.提供数据

x中开始调用触发

<button @click="sendName">点我把数据传给school</button>
methods:{
			sendName(){
				this.$bus.$emit('hello',666)
			}
		}

注意:1.我们会有很多条线调用两个组件一个方法名,这些方法名不能重复

2.我们在销毁之前要把事件解绑

4.解绑事件

在哪儿绑的在哪儿解,为啥之前的自定义事件销毁之前不去解绑呢?因为之前那些组件销毁的话身上的自定义事件就一起嘎了,但是这个无论哪个组件销毁x都一直在,组件都销毁了还留着事件那x太累了

beforeDestroy(){
			this.$bus.$off('hello')
		}

5.TodoList中的孙传父

app里传给list再传给item的函数全都不要了

mounted(){
    // this.$bus.on('checkTodo',(id)=>{
    //   this.checkTodo(id)
    // }), 不是这么写啊,这里是事件名和事件函数,我本来就是要触发那个函数,而且函数已经写好了直接用

    this.$bus.$on('deleteTodo',this.deleteTodo)
    this.$bus.$on('checkTodo',this.checkTodo)
  },
  beforeDestroy(){
    this.$bus.$off(['checkTodo','deleteTodo'])
  }

item:

methods: {
    handleCheck(id){
    this.$bus.$emit('checkTodo',id)
   },
   handleDelete(id){
     this.$bus.$emit('deleteTodo',id)
   }
   },

检查vue中如果sourse为root那一般就是$bus

二、消息订阅与发布(pubsub)

在vue里用的不多

在a(需要消息)组件里我们订阅了一个demo的消息,内容是test,然后c(提供数据、发布消息)一旦发布demo的消息并传参666,那么a就会立马收到

1.使用方法

需要引入pubsub-js库,可以在任何一个框架使用

安装pubsub:npm i pubsub-js
引入:import pubsub from 'pubsub-js

接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。

mounted(){
			// this.$bus.$on('hello',(data)=>{
			// 	console.log('我是school,我收到了',data)
			// })
			this.pubid=pubsub.subscribe('hello',(msgName,data)=>{
				console.log('dingyuele ',msgName,data)
			})
        //两个参数第一个是事件名,第二个是(事件名,数据)
		},
		beforeDestroy(){
			// this.$bus.$off('hello')
			pubsub.unsubscribe(this.pubid)
			//括号里面写‘hello’不对,每次订阅消息都有一个订阅id,类似定时器
			//上面和这里不写this找不到
		}

提供数据:

methods:{
			sendName(){
				pubsub.publish('hello',666)
			}
		}

2.TodoList中用pubsub

第三方Vue中不支持查看

我们来修改一下todolist 的delete方法,app:

import pubsub from 'pubsub-js'

//mounted:

this.pubId=pubsub.subscribe('deleteTodo',this.deleteTodo)
  },
  beforeDestroy(){
    //this.$bus.$off(['checkTodo'])
    pubsub.unsubscribe(this.pubId)
  }

item:

handleDelete(id){
     //this.$bus.$emit('deleteTodo',id)
     pubsub.publish('deleteTodo',id)
   }

然后我们之前不是说会传参过来两个吗,一个是函数名,一个是形参,但是函数名我们其实不太需要,这个里面调的是methods里面我们写好的函数,所以就用_占位一下

deleteTodo(_,id)
//传不都是传两个参数吗,用这个_占位

这里没有用箭头函数是我们的函数写在了methods里面,this(delete里的this)就是vm

(为啥要让里面函数的this指向vm?存个疑)

三、TodoList的编辑功能

1.点击获取

首先实现在每个爱好的后面再加一个按钮编辑,让文字处于input框中

在处于input框中的时候,就应该是文字在框里面,编辑完成之后又得恢复成文字样式,所以还得设置一个todo.isEdit来判断当前的todo是不是在编辑中

<span v-show="!todo.isEdit">{{todo.title}}</span>
      <input v-show="todo.isEdit" type="text" 
      :value="todo.title" > 

isEdit为true的时候,表单就出来,否则就隐藏,因为变换比较多的问题这里不用v-if

然后开始添加点击之后让isEdit为true

handleEdit(todo){
     //todo.isEdit=true 这么加只是表层加了,isEdit没有getter、setter
     //这样每次都追加的写法有点不好,因为你第一次编辑确实得加这个属性,但是第二次就没必要了
     
       this.$set(todo,'isEdit',true)
   },

但是这样会让每次点击都重新添加isEdit属性不管你以前有没有

   handleEdit(todo) {
        if (todo.isEdit !== undefined) {
            todo.isEdit = true;
        } else {
            this.$set(todo, 'isEdit', true);
        }
    },

老师讲的是hasOwnProperty方法,但是报错说我电脑没有这个我就没用

2.失去焦点

失去焦点之后,isEdit为false,表单消失,而且之前修改的内容需要改到我们的文字里面,注意传的是input表单的value而不是todo.title

<input v-show="todo.isEdit" type="text" 
      :value="todo.title" 
      @blur="handleBlur(todo,$event)"> 
//失去焦点真正执行修改
   handleBlur(todo,e){
     //现在的todo已经有isEdit属性了
     todo.isEdit=false
     this.$bus.$emit('updataTodo',todo.id,e.target.value)
   }

用全局事件来修改app里的数据,在item中触发updateTodo事件

app:遍历数组看谁的id和我传的一样就修改它的title

updateTodo(id,title){
      this.todos.forEach((todo)=>{
        if(todo.id==id) {todo.title=title}
        
      })
    },
mounted(){
    this.$bus.$on('updateTodo',this.updateTodo)
}
beforeDestroy() {
    this.$bus.$off('editTodo');
},

四、$nextTick

1、语法:this.$nextTick(回调函数)
2、作用:在下一次 DOM 更新结束,v-for循环结束后执行其指定的回调。
3、什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时(如input自动获取焦点),要在nextTick所指定的回调函数中执行。

我点击了编辑按钮之后我想让他自动获取焦点,如果直接写this.$refs.inputTitle.focus()的话,模版解析等这个函数走完了才显示在页面上,但是那个时候就focus完了,在handleEdit(todo)用$nextTick。

this.$nextTick(function (){
        this.$refs.inputTitle.focus()
      });

五、动画

1.动画效果

transition标签在html中不显示,是vue提供的,可以在style设置来去的动画,appear默认打开页面就出现 来 的动画

<button @click="isShow = !isShow">显示/隐藏</button>
    <transition name="hello" :appear="true">
        <!-- appear="true"这样会报错因为人家要的是布尔值不是字符串 -->
        <!-- :appear="true"简写为appear -->
    <h1 v-show="isShow">你好啊</h1>
    </transition>
.hello-enter-active{
    animation: atguigu 1s;
}
.hello-leave-active{
    animation: atguigu 1s reverse;
}
@keyframes atguigu {
    from{
        transform: translateX(-100%);
    }
    to{
        transform: translateX(0px);
    }
}

2.用过渡实现以上效果

元素进入的样式:
v-enter:进入的起点
v-enter-active:进入过程中
v-enter-to:进入的终点

元素离开的样式:
v-leave:离开的起点
v-leave-active:离开过程中
v-leave-to:离开的终点

.hello-enter,.hello-leave-to{
    /* 进入的起点 */
    transform: translateX(-100%);
    
}
.hello-enter-to,.hello-leave{
/* 进入的终点 */
transform: translateX(0);
}
.hello-enter-active,.hello-leave-active{
 transition: 0.5s linear;
}

3.多个元素实现过渡

transition-group

<template>
  <div>
    <button @click="isShow = !isShow">显示/隐藏</button>
    <transition-group name="hello" :appear="true">
        <!-- appear="true"这样会报错因为人家要的是布尔值不是字符串 -->
        <!-- :appear="true"简写为appear -->
    <h1 v-show="isShow" key="1">你好啊</h1>
    <h1 v-show="isShow" key="2">你好啊</h1>
    </transition-group>
  </div>
</template>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值