Vue 组件通讯(组件传值)

组件传值:组件之间的通讯

一:父组件传子组件,子组件接收

  1. 父组件传递:

    如果子组件做为标签在父组件进行使用的时候,需要在父组件内部的子组件标签上面添加自定义属性,值为需要传递的数据
    <template>
     <div id="app">
       <h1>appVue父组件</h1>
       <Child1 :dataVal="msg"/>   <!-- 在标签 绑定dataVal自定义属性 -->
     </div>
    </template>

    <script>
    import Child1 from './components/child1'
    export default {
     components:{
       Child1,
    },
     data(){
       return {
         "msg" : '父组件传递的数据'
      }
    }
    }
    </script>
  2. 子组件接收:( 在子组件内部通过props进行接收 -> props属性用来接收外部数据 )

    • 第一种接收方法:

      <template>
         <div>
             <h2>child1组件接收父组件数据:{{dataVal}}</h2>
         </div>
      </template>
      <script>
      export default {
         props : ["dataVal"]          //通过数组进行接收
      }
      </script>
    • 第二种接收方法:

      <template>
         <div>
             <h2>child1组件接收父组件数据:{{dataVal}}</h2>
         </div>
      </template>
      <script>
      export default {
         props : {
             dataVal : {     //通过对象进行接收
                 type : String,     //限制数据类型(注:如果传递的数据非当前规定的数据类型,在开发环境下控制台会有警告,但是项目仍能跑)
                 default : '默认值', //默认数据:如果父组件没有传递数据,则接收当前默认数据
                 required : true    //限制必须有数据的传递,如果没有数据传递则报出警告,
            }
        }
      }
         //注: default属性和required属性 两个选取一个存在即可。
      </script>

       

二:子组件传递,父组件接收

  1. 父组件接收:

    当子组件在父组件里面当作标签进行应用的时候,给当前子组件绑定一个自定义事件,值为需要接收值得函数,这个函数在应用得时候不需要加()
    <template>
     <div id="app">
       <h1>appVue父组件</h1>
       <p>{{msg}}</p>
       <Child2 @handleGet="getVal"/>   <!-- 给当前标签添加自定义事件,值为需要接收值得函数 -->
     </div>
    </template>

    <script>
    import Child2 from './components/child2'
    export default {
     data(){
       return {
         msg : ""
      }
    },
     components:{
       Child2,
    },
     methods : {
       getVal(val){
         this.msg = val;
      }
    }
    }
    </script>
  2. 子组件传递:

    在子组件里面需要用 this.$emit('自定义事件的名称',需要传递的参数) 进行数据传递
    <template>
       <div>
           <h3>child2组件</h3>
           <button @click="sendData">向父组件传递数据</button>
       </div>
    </template>
    <script>
    export default {
       methods: {
           sendData(){
               this.$emit('handleGet','child2传递的数据');  //this.$emit第一个参数为 父组件标签内部自定义得事件得名称
          }
      },
    }
    </script>

三:非父子组件传值

1:第一种方法:
在Vue的原型上挂一个Vue的实例,需要传递数据的一方调用 $emit     需要接收数据的一方调用$on 

弊端:因为需要在原型上挂一个Vue实例,但是我们用到的只是$on   $emit方法,所以会产生性能消耗。
  1. 在Vue的原型上挂一个Vue的实例,每个组件都能访问这个实例上面的方法 ( main.js中操作 )

    Vue.prototype.$observer = new Vue();

  2. 传递

    <template>
       <div class="box">
           <button @click="sendDate">向其他组件传递数据</button>
       </div>
    </template>
    <script>
    export default {
       methods: {
           sendDate(){
               this.$observer.$emit('getDate','child3组件传递的数据')  
          }
      },
    }
    </script>
  3. 接收

    <template>
       <div class="box">
           <h2>接受到child3组件传递的数据为:{{val}}</h2>
       </div>
    </template>

    <script>
    export default {
       data(){
           return{
               val : ''
          }
      },
       created() {    //尽量要在声明周期中使用 $on
           this.$observer.$on('getDate',(val) => {
               this.val = val;
          })
      },
    }
    </script>

     

2:第二种方法
观察者模式:封装 $on $emit $off  放在src文件下面observer.js     然后放在Vue的原型上面(在 main.js操作即可)
const eventList = {};

const $on = function(eventName,callback){
   if(!eventList[eventName]){
       eventList[eventName] = [];
  }
   eventList[eventName].push(callback);
}

const $emit = function(eventName,param){
   if(eventList[eventName]){
       let fnArr = eventList[eventName];
       fnArr.forEach((callback) => {
           callback(param);
      });
  }
}
const $off = function(eventName,callback){
   if(eventList[eventName]){
       if(callback){
           let index = eventList[eventName].indexOf(callback);
           eventList[eventName].splice(index,1);
      }else{
           eventList[eventName].length = 0;
      }
  }
}
export default {
   $on,
   $emit,
   $off
}
//在main.js操作引入、在Vue原型上添加
import observer from './observer'
Vue.prototype.$observer = observer;
  1. 传递数据

    <template>
       <div class="box">
           <h1>组件5</h1>
           <button @click="sendData">向组件6传值</button>
       </div>
    </template>
    <script>
    export default {
       methods: {
           sendData(){
               this.$observer.$emit('getVal','child5组件传递的数据')
          }
      },
    }
    </script>
  2. 接收数据

    <template>
       <div class="box">
           <h1>组件6</h1>
           <h2>接收组件5中传递的数据 {{val}}</h2>
       </div>
    </template>
    <script>
    export default {
       data(){
           return{
               val : ''
          }
      },
       created() {
           this.$observer.$on('getVal',(val) => {
               this.val = val;
          })
      },
    }
    </script>
3:第三种方法 EventBus的使用
//创建event-bus.js文件
import Vue from 'vue';
export const EventBus = new Vue();
  1. 发送数据

    <template>
       <div class="box">
           <h1>child7组件</h1>
           <button @click="sendMsg">向组件8传递数据</button>
       </div>
    </template>

    <script>
    import {EventBus} from '../event-bus'
    export default {
       methods: {
           sendMsg(){
               EventBus.$emit('getVal','组件7中所传递的数据');
          }
      },
    }
    </script>
  2. 接收数据

    <template>
       <div class="box">
           <h1>child8组件</h1>
           <h2>接收组件7中的数据:{{val}}</h2>
       </div>
    </template>

    <script>
    import {EventBus} from '../event-bus'
    export default {
       data(){
           return {
               val :''
          }
      },
       created() {
           EventBus.$on('getVal',(val) => {
               this.val = val;
          })
      },
    }
    </script>
posted @ 2020-04-06 18:13  Bruce胖子  阅读(288)  评论(0编辑  收藏  举报