目录
数据以形参的形式传递
消息订阅与发布(pubsub)
1.一种组件间通信的方式,用于任意组件间通信
2.使用步骤
1)安装pubsub:
npm i pubsub-js
2)引入
import pubsub from 'pubsub-js'
3)接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调在A组件自身
methods(){
demo(data){..........}
}
............
mounted(){
this.pid=pubsub.subscribe('xxx',this.demo)
//订阅消息
}
4)提供数据:
pubsub.publish('xxx',数据)
5.最好在beforeDestory钩子中,用pubsub.unsubscribe(pid) 去取消订阅
school.vue
<template>
<div class="school">
<h2>学校名称:{{ name }}</h2>
<h2>学校地址:{{ address }}</h2>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: "School",
data() {
return {
name: "尚硅谷",
address: "北京",
}
},
methods:{
demo(msgName,data){
console.log('hello消息收到了',data,this);
}
},
mounted(){
// console.log('school',this);
// this.$bus.$on('hello',(data)=>{
// console.log("我是school组件,收到了数据",data)
// })
// this.pubId=pubsub.subscribe('hello',(msgName,data)=>{
// console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data);
// })
this.pubId=pubsub.subscribe('hello',this.demo)
},
beforeDestroy(){
// this.$bus.$off('hello')
pubsub.unsubscribe(this.pubId)
},
}
</script>
<style scoped>
.school {
background-color: skyblue;
padding: 5px;
}
</style>
student.vue
<template>
<div class="student">
<h2>学生姓名:{{ name }}</h2>
<h2>学生性别:{{ sex }}</h2>
<button @click="sendStudentName">把学生名字给school组件</button>
</div>
</template>
<script>
import pubsub from 'pubsub-js'
export default {
name: "Student",
data() {
return {
name: "张三",
sex: "男"
};
},
mounted(){
// console.log('student',this.x);
},
methods:{
sendStudentName(){
// 触发事件
// this.$bus.$emit('hello',this.name)
pubsub.publish('hello',666)
}
}
};
</script>
<style lang="less" scoped>
.student {
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
TodoList案例消息订阅与发布
需要数据的地方订阅消息,提供数据的地方发布消息
nextTick
语法:
this.$nextTick(回调函数)
作用:在下一次DOM更新结束后执行其指定的回调
什么时候用:当噶便数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行
myitem.vue
<template>
<li>
<label>
<input
type="checkbox"
:checked="todo.done"
@change="handleCheck(todo.id)"
/>
<span v-show="!todo.isEdit">{{ todo.title }}</span>
<input
v-show="todo.isEdit"
type="text"
:value="todo.title"
@blur="handleBlur(todo, $event)"
ref="inputTitle"
/>
</label>
<button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
<button
v-show="!todo.isEdit"
class="btn btn-edit"
@click="handleEdit(todo)"
>
编辑
</button>
</li>
</template>
<script>
import pubsub from "pubsub-js";
export default {
name: "MyItem",
// 声明接收todo对象
props: ["todo"],
methods: {
// 勾选、取消勾选
handleCheck(id) {
// console.log(id);
// 通知App组件将对应的todo对象的done取反,数据在哪里,操作对象的数据在哪里
// this.checkTodo(id);
this.$bus.$emit("checkTodo", id);
},
// 删除数据
handleDelete(id) {
// 根据用户的反应来确定是否进行
if (confirm("确定删除吗?")) {
// deleteTodo是父组件的函数名
// this.deleteTodo(id)
// console.log(id);
// 借助全局事件总线,自定义事件的事件名
// this.$bus.$emit('deleteTodo',id)
// 订阅消息的消息名
pubsub.publish("deleteTodo", id);
}
},
// 编辑,目的是为了使文字变成输入框
handleEdit(todo) {
if (todo.hasOwnProperty("isEdit")) {
todo.isEdit = true;
} else {
console.log("todo身上没有isEdit");
this.$set(todo, "isEdit", true);
}
// nextTick(下一轮)所指定的回调会在dom节点更新之后再执行
this.$nextTick(function () {
this.$refs.inputTitle.focus();
});
// 把文字变成输入框后,就让输入框获取焦点
// 但是这句代码不能实现,是因为
// 这样只能生硬的添加属性,不能使页面发声改变
// todo.isEdit=true
},
// 失去焦点回调(真正执行修改逻辑)
handleBlur(todo, e) {
todo.isEdit = false;
// console.log('updateTodo',todo.id,e.target.value);
// 判断它输入是否为空
if (!e.target.value.trim()) return alert("输入不能为空");
this.$bus.$emit("updateTodo", todo.id, e.target.value);
},
},
};
</script>
<style>
/* item */
li {
list-style: none;
height: 36px;
line-height: 36px;
padding: 0 5px;
border-bottom: 1px solid #ddd;
}
li label {
float: left;
cursor: pointer;
}
li label li input {
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
li button {
float: right;
display: none;
margin-top: 3px;
}
li:before {
content: initial;
}
li:last-child {
border-bottom: none;
}
li:hover {
background-color: #ddd;
}
li:hover button {
display: block;
}
</style>