2.4 组件通信

Props 和 Events(父子组件通信)

Vue 2 中,props 被设计为只读,以确保数据流从父组件到子组件的单向流动,避免不必要的数据绑定复杂性和潜在的错误。

如果要修改,需要用下边的 子组件向父组件传递参数,在父组件中根据传递过来的值,修改parentMessage的值

  • Props :父组件向子组件传递数据使用 props。子组件通过声明 props 来接收来自父组件的数据。

    复制代码
    <!-- 父组件 -->
    <template>
      <ChildComponent :message="parentMessage" />
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: { ChildComponent },
      data() {
        return {
          parentMessage: 'Hello from parent'
        };
      }
    };
    </script>
    
    <!-- 子组件 -->
    <template>
      <div>{{ message }}</div>
    </template>
    
    <script>
    export default {
      props: ['message']
    };
    </script>
  • Events :子组件向父组件发送消息或数据可以使用 $emit 方法触发自定义事件。

    复制代码
    <!-- 子组件 -->
    <template>
      <button @click="sendMessage">Send Message</button>
    </template>
    
    <script>
    export default {
      methods: {
        sendMessage() {
          this.$emit('childEvent', 'Hello from child');
        }
      }
    };
    </script>
    
    <!-- 父组件 -->
    <template>
      <ChildComponent @childEvent="handleChildEvent" />
    </template>
    
    <script>
    import ChildComponent from './ChildComponent.vue';
    
    export default {
      components: { ChildComponent },
      methods: {
        handleChildEvent(message) {
          console.log(message);
          //上个例子中.可以通过this.parentMessage = message 
            //实现子组件 修改prop里的属性值  
        }
      }
    };
    </script>

ChildComponent.vue,它需要向父组件发送两个参数:messagestatus

复制代码
<template>
  <button @click="sendDataToParent">Send Data to Parent</button>
</template>

<script>
export default {
  data() {
    return {
      message: 'Hello from Child',
      status: 'success'
    };
  },
  methods: {
    sendDataToParent() {
      // 使用 $emit 触发自定义事件,并传递多个参数
      this.$emit('dataFromChild', this.message, this.status);
    }
  }
};
</script>

在这个例子中,当按钮被点击时,会调用 sendDataToChild 方法,该方法使用 $emit 来触发名为 dataFromChild 的自定义事件,并传递了两个参数:this.messagethis.status

父组件代码

接下来,在父组件中引入 ChildComponent 并监听 dataFromChild 事件。

复制代码
<template>
  <div>
    <!-- 监听来自子组件的自定义事件 -->
    <ChildComponent @dataFromChild="handleDataFromChild" />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  methods: {
    handleDataFromChild(message, status) {
      console.log('Message:', message); // 输出: Hello from Child
      console.log('Status:', status);   // 输出: success
      // 在这里处理接收到的数据
    }
  }
};
</script>

在这个父组件的例子中,@dataFromChild="handleDataFromChild" 表示监听子组件发出的 dataFromChild 事件,并在事件发生时调用 handleDataFromChild 方法。此方法接收子组件传递过来的参数(在这个例子中是 messagestatus),然后可以根据业务需求对这些数据进行处理。

这种方法可以让你轻松地在子组件和父组件之间传递任意数量的参数。只需要确保在 $emit 调用时传递正确的参数,并在父组件的方法中正确接收它们即可

父组件在监听子组件事件的同时,还需要传递自己的参数

  • 子组件通过 $emit 触发事件,传递自己的数据(如:childData)。
  • 父组件监听该事件,同时还想传入自己的参数 (如:parentId, category 等)。
  • 最终父组件的处理函数需要 同时拿到子组件的数据 + 父组件自己的参数

方法一:使用内联箭头函数(推荐)

这是最清晰、最常用的方式。

复制代码
<!-- 父组件 ParentComponent.vue -->
<template>
  <div>
    <!-- 使用箭头函数包装,同时传入父组件参数 -->
    <ChildComponent
      @dataFromChild="(childData) => handleData(childData, parentId, 'user')"
    />
  </div>
</template>

<script>
import ChildComponent from './ChildComponent.vue';

export default {
  components: { ChildComponent },
  data() {
    return {
      parentId: 1001,
    };
  },
  methods: {
    handleData(childData, parentId, type) {
      console.log('来自子组件的数据:', childData);
      console.log('父组件自己的参数:', parentId, type);
      // 处理逻辑...
    }
  }
};
</script>

✅ 优点:语义清晰,支持传任意多个父参数。


方法二:使用包装函数(命名函数)

如果你不想用内联箭头函数,也可以封装一个中间函数。

复制代码
<template>
  <ChildComponent @dataFromChild="wrapperHandler" />
</template>

<script>
export default {
  data() {
    return {
      parentId: 1001,
    };
  },
  methods: {
    wrapperHandler(childData) {
      // 在这里调用真正的处理函数,并传入父组件参数
      this.handleData(childData, this.parentId, 'admin');
    },
    handleData(childData, parentId, role) {
      console.log(childData, parentId, role);
    }
  }
};
</script>

✅ 优点:逻辑分离,适合复杂逻辑。


✅ 方法三:使用 $event 隐式变量(传统方式)

Vue 会把 $emit 的第一个参数自动传给监听函数,可以用 $event 接收。

复制代码
<template>
  <ChildComponent @dataFromChild="handleData($event, parentId, 'guest')" />
</template>

<script>
export default {
  data() {
    return {
      parentId: 1001,
    };
  },
  methods: {
    handleData(childData, parentId, userType) {
      console.log(childData, parentId, userType);
    }
  }
};
</script>

⚠️ 注意:$event 是子组件 $emit 传递的第一个参数。如果有多个参数,$event 只是第一个。如果要传递多个,可以把参数包装成一个对象.

复制代码
<!-- ChildComponent.vue -->
<template>
  <button @click="sendData">Send Data</button>
</template>

<script>
export default {
  methods: {
    sendData() {
      this.$emit('dataFromChild', {
        name: 'Alice',
        age: 25
      });
    }
  }
};
</script>

✅ 总结

方法 说明 推荐度
内联箭头函数 (data) => handler(data, param) 最灵活,推荐 ⭐⭐⭐⭐⭐
包装函数 逻辑清晰,适合复杂处理 ⭐⭐⭐⭐☆
$event + 参数 传统写法,稍显隐晦 ⭐⭐⭐☆☆

相关推荐
子兮曰6 小时前
Bun v1.3.14 深度解析:Image API、HTTP/3、全局虚拟存储与五十项变革
前端·后端·bun
kyriewen7 小时前
今天,百年巨头一次砍了9200人,而一个离职科学家的实话让全网睡不着觉
前端·openai·ai编程
问心无愧05137 小时前
ctf show web 入门42
android·前端·android studio
kyriewen8 小时前
老板逼我上AI,我偷偷在浏览器里跑LLaMA,省下20万API费
前端·react.js·llm
Beginner x_u8 小时前
前端八股整理(手写 02)|数组转树、数组扁平化、随机打乱一个数组
前端·数组·数组转树·数组扁平化
KaMeidebaby8 小时前
卡梅德生物技术快报|禽类成纤维细胞 FISH 实验:鸟类性别染色体基因定位技术实现与数据验证
前端·数据库·其他·百度·新浪微博
天若有情6738 小时前
前端高阶性能优化:跳出传统懒加载与预加载,基于用户行为做轻量预判加载
前端·性能优化
小小小小宇8 小时前
前端转后端:SQL 是什么
前端
张元清9 小时前
React Observer Hooks:7 种监听 DOM 而不写样板代码的方式
前端·javascript·面试
广州华水科技9 小时前
单北斗GNSS变形监测是什么?主要有怎样的应用与优势?
前端