vue(11)

全局事件总线(GlobalEventBus)

1.一种组件间通信的方式,适用于任意组件间通信

2.安装全局事件总线

3.使用事件总线:

1)接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件的回调留在A组件中自身

 2)提供数据

this.$bus.$emit('xxxx',数据)

4.最好在beforeDestory钩子中,用$off去解绑当前组件用到的事件

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

事件被触发,事件对应的回调会执行

哪里引入的vue,就在哪里操作vue

实际就是把x放在Vue的原型对象上

在mounted函数中,写触发函数时要写箭头函数做回调

vm----整个应用new出来的vue

vc----组件实例对象

全局的vc vm都通过$bus传递

 数据在哪里,操作数据的地方在哪里

todolist事件总线

app.vue

<template>
  <div id="root">
    <div class="todo-container">
      <div class="todo-warp">
        <MyHeader @addTodo="addTodo"/>
        <!-- 将todos传给MyList,命名为todos -->
        <MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
        <MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"/>
      </div>
    </div>
  </div>
</template>

<script>
// 引入school组件
import MyHeader from "./componments/MyHeader.vue";
import MyFooter from "./componments/MyFooter.vue";
import MyList from "./componments/MyList.vue";


export default {
  name: "App",
  components: {MyHeader,MyFooter,MyList},
  data(){
    return{
      // 由于todos是MyHeader组件和MyFooter组件都在使用,所以放在App中(状态提升)
      // 数组为null时,length会报错,所以用[]
      todos:JSON.parse(localStorage.getItem('todos')) || []
    }
  },
  methods:{
    // 添加一个todo
    addTodo(todoObj){
      // console.log(todoObj);
      this.todos.unshift(todoObj)
    },
    // App和Item是爷孙关系,逐层传递,需要app传给list,list传给item
    // 勾选或取消勾选一个todo
    checkTodo(id){
      this.todos.forEach((todo)=>{
        if(todo.id===id)  todo.done==!todo.done
      })
    },
    // 删除一个todo
    deleteTodo(id){
      // 用过滤器过滤掉等于id的对象
      this.todos=this.todos.filter(todo=>todo.id!==id)
    },
    // 全选或取消全选
    checkAllTodo(done){
      this.todos.forEach((todo)=>{
        todo.done=done
      })
    },
    // 清除所有已经完成的todo
    clearAllTodo(){
      // 过滤不会影响原数据,所以要在前面加this.todos=
      this.todos=this.todos.filter((todo)=>{
        return !todo.done
      })
    }
  },
  watch:{
    todos:{
      deep:true,
      handler(value){
        localStorage.setItem('todos',JSON.stringify(value))
      }
    }
  },
  mounted(){
    this.$bus.$on('addTodo',this.addTodo)
    this.$bus.$on('checkTodo',this.checkTodo)
    this.$bus.$on('deleteTodo',this.deleteTodo)
  },
  beforeDestroy(){
    this.$bus.$off('addTodo')
    this.$bus.$off('checkTodo')
    this.$bus.$off('deleteTodo')

  }
};
</script>
<style>
  /* 基本样式,所有的都在用 */
  /* base */
  body{
    background: #fff;
  }
  .btn{
    display:inline-block;
    padding: 4px 12px;
    margin-bottom:0;
    font-size:14px;
    line-height: 20px;
    text-align: center;
    vertical-align: middle;
    cursor:pointer;
    box-shadow: inset 0 1px 0 rgba(255,255,255,0.2),0 1px 2px rgba(0,0,0,0.05);
    border-radius: 4px;
  }
  .btn-danger{
    color:#fff;
    background-color: #da4f49;
    border: 1px solid #bd362f;
  }
  .btn-danger:hover{
    color:#fff;
    background-color: #bd362f;
  }
  .btn:fouse{
    outline:none;
  }

  .todo-container{
    width: 600px;
    margin:0 auto;
  }
  .todo-container .todo-wrap{
    padding: 10px;
    border: 1px solid #ddd;
    border-radius: 5px;

  }
</style>

myitem.vue

<template>
  <li>
    <label>
      <input
        type="checkbox"
        :checked="todo.done"
        @change="handleCheck(todo.id)"
      />
      <span>{{ todo.title }}</span>
    </label>
    <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
  </li>
</template>

<script>
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('确定删除吗?')){
        // this.deleteTodo(id)
        // console.log(id);
        this.$bus.$emit('deleteTodo',id)

      }
    }
  },
};
</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>

mylist.vue

<template>
  <ul class="todo-main">
       <MyItem 
    v-for="todoObj in todos" 
    :key="todoObj.id" 
    :todo="todoObj" />
  </ul>
</template>

<script>
import MyItem from "./MyItem.vue";
export default {
  name: "List",
  components: { MyItem },
  props:['todos'],
  
};
</script>

<style scoped>
/* main */
.todo-main {
  margin-left: 0px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding: 0px;
}

.todo-empty {
  height: 40px;
  line-height: 40px;
  border: 1px solid #ddd;
  border-radius: 2px;
  padding-left: 5px;
  margin-top: 10px;
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值