Vue子组件emit传值父组件收到PointerEvent对象问题排查
问题根因
- 事件监听对象错误:父组件没有监听子Button抛出的自定义
click事件,反而在自身根DOM节点上绑定了原生click事件,点击子组件时事件冒泡触发该原生事件,接收到的参数自然是原生PointerEvent对象,而非子组件传递的宽度数据 - 子组件模板语法错误:
<div class="button @click="click" ref="button">中class属性缺少闭合引号,会导致模板解析异常 - 自定义事件命名歧义:自定义事件使用原生DOM事件名
click,容易和原生事件混淆引发逻辑异常 - 父组件模板语法错误:插槽未用
<slot/>标签声明,slider节点未闭合
修复方案
第一步:修改子组件(Button)
<template> <!-- 补全class属性闭合引号 --> <div class="button" @click="handleClick" ref="button"> <slot /> </div> </template> <script> import { ref } from 'vue' export default { name: 'Button', // 自定义事件名改为非原生事件名避免歧义,同时传递滑块需要的left和width两个参数 emits: ['tab-click'], data () { return { width: '', left: '' } }, setup() { const button = ref(null) return { button } }, mounted () { this.$nextTick(() => { this.left = Math.ceil(this.button.getBoundingClientRect().left) this.width = Math.ceil(this.button.getBoundingClientRect().width) }) }, methods: { handleClick () { this.$emit('tab-click', { width: this.width, left: this.left }) console.log(`${this.width} has been emitted to the tabs component`) } } } </script>
第二步:修改父组件(Tabs)
<template> <div class="tabs"> <!-- 正确声明插槽 --> <slot/> </div> <!-- 补全slider闭合标签,style绑定接收完整的样式对象 --> <div class="slider" :style="sliderStyle"></div> </template> <script> import Button from './Button.vue' export default { name: 'Tabs', components: { Button }, data () { return { // 调整为样式对象,支持同时设置宽度和偏移量 sliderStyle: { width: '0px', left: '0px' } } }, methods: { updateSlider ({ width, left }) { // 拼接合法的CSS样式值 this.sliderStyle = { width: `${width}px`, left: `${left}px` } console.log(`${width} has been received and assigned by parent`) } } } </script>
第三步:调用时绑定自定义事件
在使用Tabs组件的页面,给每个插入的Button绑定tab-click事件即可:
<Tabs> <Button @tab-click="updateSlider">标签1</Button> <Button @tab-click="updateSlider">标签2</Button> <Button @tab-click="updateSlider">标签3</Button> </Tabs>
内容的提问来源于stack exchange,提问作者Chelsey Machin
相关产品推荐
相关产品推荐

