全局事件总线(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
- <div id="root">
- <div class="todo-container">
- <div class="todo-warp">
- <MyHeader @addTodo="addTodo"/>
-
- <MyList :todos="todos" :checkTodo="checkTodo" :deleteTodo="deleteTodo"/>
- <MyFooter :todos="todos" :checkAllTodo="checkAllTodo" :clearAllTodo="clearAllTodo"/>
- div>
- div>
- div>
-
- <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
- <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>
-
- <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
- <ul class="todo-main">
- <MyItem
- v-for="todoObj in todos"
- :key="todoObj.id"
- :todo="todoObj" />
- ul>
-
- <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>