vue父子、兄弟组件之间传值基本用法实现

前言:

        组件是 vue.js 最强大的功能之一,而组件实例的作用域之间是相互独立的,这就意味着不同组件之间的数据无法相互引用。一般来说,组件可以有以下几种关系:

        1.父子

        2.兄弟

        3.跨级

 本章只提供最基本的用法如下:

        方法一、props/$emit

          父组件 A 通过 props 的方式向子组件 B 传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。

        方法二、$emit/$on

          这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。
  注:当我们的项目比较大时,可以选择更好的状态管理解决方案 vuex。(这里不作多说)

不多说废话,直接上实现结果,如图:

父组件引用子组件MyInput、MyList、MyTotal,分为三块:input输入、ul列表显示、以及控制显示按钮。父组件代码如下:

<template>
  <div class="layout">
    <h1>{{ msg }}</h1>
    <MyInput @add="add"/>
    <MyList :list="list" @del="del" @ret="ret"/>
    <MyTotal/>
  </div>
</template>

<script>
import MyInput from './test/Input.vue'
import  MyList  from './test/List.vue'
import  MyTotal  from './test/Total.vue'

export default {
  name: 'HelloWorld',
  components:{
    MyInput,MyList,MyTotal
  },
  data () {
    return {
      msg: 'Todolist',
      list:[
        {id:0,value:'打台球',status:0},
        {id:1,value:'洗碗',status:1},
        {id:2,value:'晒被子',status:0},
      ] 
    }
  },
  mounted(){
    // console.log(Math.floor(Math.random() * 10000),1111)
  },
  methods:{
    add(title){
      this.list.push({
        id:Math.floor(Math.random() * 1000),
        value:title,
        status:0
      })
    },
    del(id){
      console.log(id,222);
      const newList = this.list.filter(item=>item.id!==id)
      this.list = newList
    },
    ret(id){
      console.log(id,222);
      if(this.list[id].status === 0){
        this.list[id].status = 1
      }else{
        this.list[id].status = 0
      }
    }
  }
}
</script>

MyInput子组件代码如下:

<template>
    <div class="myInput">
     <input type="text" v-model="title"/>
     <el-button type="primary" size="mini" @click="add">添加新事项</el-button>
    </div>
</template>

<script>
import event from './event'
export default {
    data(){
        return {
            title:''
        }
    },
    methods:{
        add(){
            if(this.title === ''){
                alert('请输入代办事件!')
                return
            }
            this.$emit('add',this.title)   
            event.$emit('changeDom')
        }
    }
}
</script>

(事件中心)

如图中引用的event,来源何处呢?如果只是引用没有引入,那肯定是被丢弃的。这是我们需要引入一个event.js,如下:

由此看到,event.js只是引入了vue实例,所以以下子组件中使用的event都是vue的实例而已。

MyList子组件代码如下:

<template>
    <div class="myList">
        <template v-if="myStatus === 0">
            <ul>
                <li  v-for="(item,index) in list" :key="item.id">
                    <div class="text">
                        <span >{{item.value}}  </span>
                        <span v-if="item.status === 0"> [代办]</span>
                        <span v-if="item.status === 1"> [已办]</span>
                    </div>
                    <div class="bnt">
                        <el-button  type="success" size="mini" @click="ret(item.id)">切换</el-button>
                        <el-button type="danger" size="mini" @click="del(item.id)">删除</el-button>
                    </div>  
                </li>
            </ul>
        </template>
        <template v-if="myStatus === 1">
            <ul>
                <li  v-for="(item,index) in list" :key="item.id">
                    <div class="text" v-if="item.status === 0"><span >{{item.value}}</span></div>
                    <div class="bnt">
                    </div>  
                </li>
            </ul>
        </template>
        <template v-if="myStatus === 2">
            <ul>
                <li  v-for="(item,index) in list" :key="item.id">
                    <div class="text" v-if="item.status === 1"><span >{{item.value}}</span></div>
                    <div class="bnt">
                    </div>  
                </li>
            </ul>
        </template>
    </div>
</template>

<script>
import event from './event'
export default {

    props:{
        list:{
            type: Array
        }
    },
    data(){
        return {
            myStatus:0
        }
    },
    mounted(){
        event.$on('oAttle',this.myLog)
        event.$on('changeDom',this.changeDom)
    }, 
    methods:{
        del(id){
            this.$emit('del', id)
            event.$emit('onAttle', id)
        },
        myLog(status){
            this.myStatus = status
            event.$emit('changeColor',this.myStatus)
        },
        changeDom(){
            this.myStatus =0
        },
        ret(id){
            this.$emit('ret',id)
        }
    },
    beforeDestroy(){
        // 及时销毁,防止内存泄漏
        event.$off('oAttle',this.myLog)
        event.$off('changeDom',this.changeDom)
    }
}
</script>

MyTotal子组件代码如下:

<template>
    <div class="myList">
        <el-button :type="butClor[0].type" size="mini" @click="myClick(statusArry[0])">全部</el-button>
        <el-button :type="butClor[1].type" size="mini" @click="myClick(statusArry[1])">代办</el-button>
        <el-button :type="butClor[2].type" size="mini" @click="myClick(statusArry[2])">已办</el-button>
    </div>
</template>

<script>
import event from './event'
export default {

    data(){
        return {
           statusArry:[0,1,2],
           butClor:[
            {id:0,type:"primary"},
            {id:1,type:"primary"},
            {id:2,type:"primary"}
           ]
        }
    },
    mounted(){
        event.$on('changeColor',this.changeColor)
    }, 
    methods:{
        myClick(val){
            if(val === 0){
                event.$emit('oAttle',this.statusArry[0])
            }else if(val === 1){
                event.$emit('oAttle',this.statusArry[1])
            }else{
                event.$emit('oAttle',this.statusArry[2])
            }
        },
        changeColor(status){
            this.butClor = [
            {id:0,type:"primary"},
            {id:1,type:"primary"},
            {id:2,type:"primary"}
           ]
        //     if(status === 0){
        //        this.butClor[0].type = 'danger'
        //     }else if(status === 1){
        //         this.butClor[1].type = 'danger'
        //     }else{
        //         this.butClor[2].type = 'danger'
        //     }
            this.butClor[status].type='danger'
        }
    },
    beforeDestroy(){
        event.$off('changeColor',this.changeColor)
    }
}
</script>

总结

常见使用场景可以分为三类:

  • 父子通信:父向子传递数据是通过 props,子向父是通过 events($emit)

    也可以通过父链 / 子链也可以通信($parent/$children)ref 也可以访问组件实例(本章不做多说)
  • 兄弟通信:  $emit/$on、Bus

  • 跨级通信:Vuex、Bus

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值