vue 组件中如何传值并且监听

560 阅读1分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

组件通信主要有以下几种方式: props,$emit和$on,vuex,$attrs和$listeners,provide和inject,$parent,$children与 ref,evenbus以及 $root 按使用场景可以划分为以下三类:

1.     父子组件通信
         props
         $emit和$on
         $parent和$children
         ref
         $attrs和$listeners
2.    兄弟组件通信
         $parent
         $root
         eventBus
         vuex
3.    跨层级通信
         eventBus
         provide和inject
         vuex

  1. 父组件向子组件传值:使用prop向子组件传值;
  2. 子组件实时监听父组件传来的值的变化:使用watch去监听父组件传来的值;
  3. 父组件可以通过this.$refs.name.去访问子组件的值或方法;
  4. 子组件可以通过this.$parent.去访问父组件的值或方法;

父组件向子组件传值

这是父子间组件通信的常见方式,一般用于父组件向子组件传递数据,并且是响应式的。一般情况下子组件不会去直接改变从父组件同过 prop 传过来的数据,如果想改变的话,一般会在子组件 data 中定义一个变量来进行接收:

1. 引入子组件
import child '@/components/child'
2. components 中加入子组件
components:{child},
3. 定义数据
dataList:[{id:'1',name:'2'}]
1. 使用props 定义数据类型
props:{
      dataList:{
        type:Array,
        require:true,
      }
    },
2. watch中进行监听
watch(){
    dataList(data){
        ...  //  根据实际业务需求
    }
},

子组件向父组件传值 ($emit()可以传多个值

$emit和$on这 种通信方式主要是解决子组件向父组件传递数据的问题。不适合数据隔代传递(跨组件)。

1. 定义一个事件触发执行 (子组件中)
<button @click="a"></button>
2. 执行方法
this.$emit("show","我是子组件的数据")
3. 父组件接收数据  (直接写在created 中,但这样只是初始化才会加载,跟设计不符合 如下)
 this.$on("show",data=>{
      console.log(data);
 })
 
<template>
  <div style="height:100%">
    <transition name="ams-drawer-transform" >
      <report-collect-main @show="show" v-show="currentView=='main'" />
      </transition>
      <report-collect-add @show="show" v-show="currentView=='add'"/>  <!-- 手工录入 -->
      <report-collect-setvolume @show="show" v-show="currentView=='setvolume'" />  <!-- 组卷 -->
      <report-collect-handover @show="show"  v-show="currentView=='handover'" />  <!-- 交接 -->
      <report-collect-transferlist @show="show" v-show="currentView=='transferlist'" />  <!-- 交接清单 -->
  </div>
</template> 

这样写法在主页页面加载时候就会初始化所有,这种方式不适合,只能抛弃了

第二种方式

1. this.$emit("show","我是子组件的数据")  //子组件
   然后在父组件中声明一个show方法
2. 在父组件methods 创建一个方法用来接收子组件传过的数据
   methods: {
       show(val){
           console.log("我是子组件数据");
       },
   }

子组件向父子件传,父组件向子组件传

1. 父组件中引入所有子组件
2. 引入之后加入 components
3. 子组件使用 this.$emit()进行传值
4. 父组件中接收数据
   <proof-collect-handover @show="show"  v-show="currentView=='handover'" />    //父组件中引入的子组件  show为定义的方法
5. methods 中创建show 方法
   methods: {
       show(val){
           console.log("我是子组件数据");
       },
   } 
6. 动态定义一个方法 加入 :handoverList="handoverList"
 <proof-collect-handover @show="show"  v-show="currentView=='handover'" />     
 <proof-collect-handover @show="show" :handoverList="handoverList" v-show="currentView=='handover'" />
7. 去子组件中声明接收该集合
props:{
      handoverList:{
        type:Array,  //声明为是Array类型的
        require:true,   // 必须传
      }
    },
8. 监听数据变化    
watch: {
    handoverList(val){
        this.tableData = val;
    }
}

$parent(获取当前组件的父组件实例)和$children(获取当前组件的子组件实例)

  1. 适用情况父子之间
1. $parent -父组件把方法传入子组件中, 子组件里直接调用这个方法
  this.$parent.data //可以是方法,可以是数据
2. $child - 当前实例的直接子组件。需要注意 `$children` 并不保证顺序,也不是响应式的.
   $children为当前组件的直接子组件,是一个无序的数组
   this.$children[0].data = "pass children set value";

ref

1. 定义ref 
<div> <!-- 定义ref -->
<p ref="refs">ref测试</p>
<button @click="show">使用ref</button> </div>
2. 引入子组件
import ....
3. 操作
this.$refs.refs.data
4.注意
 eg:子组件里el-table不是唯一组件,this.$refs.refs.$children[0]找到table组件

bus

1. bus.js文件内容
   import Vue from 'vue'
   // export default new Vue()
   const Bus = new Vue()
   export default Bus
2. 局部引用一般是兄弟之间,如果操作频繁不推荐,可以直接使用vuex
   import vueEvent from '@/api/.../.../vueEvent.js'
3. 全局引用 在main.js里面直接引用
   import Bus from '../src/bus' //这是我的路径,正确引用你们的路径
   Vue.prototype.$bus = Bus
4.赋值(局部)
  vueEvent.$emit('data',this.parentData);
5.取值(局部)
   mounted(){  // 钩子函数
      let that = this;  // 先关闭,然后再接收
      vueEvent.$off("data")
      vueEvent.$on('data',function(array){
        console.log(array)
      });
    },
6. 赋值(局部)
   this.$bus.$emit("busEvent", this.message);
7. 取值(局部)
   //用局部引用的时候 this.$bus改成Bus,跟上面引用的名字一样 
   this.$bus.$on("data", (data) => { 
          console.log(data)
       }); 
   },

vuex

1. store 文件夹下,根据不同模块进行区分 eg:./user/user.js
    const user = {
      state: {
        token: getToken(),
        name: '',
      },
    mutations: {
        SET_TOKEN: (state, token) => {
          state.token = token
        },
        SET_NAME: (state, name) => {
          state.name = name
        },
    },
    赋值 $this.commit('SET_TOKEN', res.data.token)
2.  取值
    3.1 $this.$store.state.name
    使用`mapState`辅助函数简写代码
    3.2 computed: {
        ...mapState({
            name: state => state.user.name,
          }),
    }