uni-app nvue引入vue组件时,获取data-*的数据结构不正确,且整页为vue情况下,子组件@tap事件无法获取data-*的数据

发布于 1周前 作者 zlyuanteng 来自 Uni-App

uni-app nvue引入vue组件时,获取data-*的数据结构不正确,且整页为vue情况下,子组件@tap事件无法获取data-*的数据

类别 信息
产品分类 uniapp/App
PC开发环境 Windows
PC版本号 window 10
HBuilderX类型 正式
HBuilderX版本 4.29
手机系统 iOS
手机版本号 iOS 14
手机厂商 苹果
手机机型 iphone 6s
页面类型 nvue
vue版本 vue2
打包方式 云端
项目创建方式 HBuilderX

示例代码:

tapOption(e) {  
    console.log(e)  
    // #ifdef APP-NVUE  
        var index = e.currentTarget.attr.dataIndex  
    // #endif  

    // #ifndef APP-NVUE  
        var index = e.currentTarget.dataset.index  
    // #endif  

    this.$emit('tapindex', {detail: {index: index}})  
}

操作步骤:

  • 点击列表下的某一栏

预期结果:

{
    "type": "click",  
    "timeStamp": 1731902250741,  
    "target": {  
        "id": "",  
        "attr": {  
            "dataIndex": 2  
        },  
        "offsetLeft": 0,  
        "offsetTop": 0  
    },  
    "currentTarget": {  
        "id": "",  
        "attr": {  
            "dataIndex": 2  
        },  
        "offsetLeft": 0,  
        "offsetTop": 0  
    },  
    "detail": {},  
    "stopPropagation": "function() { [native code] }"  
}

实际结果:

{
    "type": "click",  
    "timeStamp": 1731902250741,  
    "target": {  
        "id": "",  
        "dataset": {  
            "index": 2  
        },  
        "offsetLeft": 0,  
        "offsetTop": 0  
    },  
    "currentTarget": {  
        "id": "",  
        "dataset": {  
            "index": 2  
        },  
        "offsetLeft": 0,  
        "offsetTop": 0  
    },  
    "detail": {},  
    "stopPropagation": "function() { [native code] }"  
}

走的位置是:

// #ifdef APP-NVUE
var index = e.currentTarget.attr.dataIndex
// #endif

是没错的

bug描述:

index.nvue 引用了一个 子组件:report-box.vue,在子组件的列表下每栏都有点击事件:[@tap](/user/tap)="tapOption" :data-index="index",在nvue的情况下,获取index 应该是 e.currentTarget.attr.dataIndex,而不是 e.currentTarget.dataset.index


7 回复

看你的代码:@tap=“tapOption” :data-index=“index”, 调用子组件的地方,是能拿到index的。如果是想父组件获取点击的子组件的index的话,这样写: 父组件中: <reportBox @click=“showIndex(index)” />


你这个是整块子组件的点击事件,我这个是子组件下的 某个栏目的点击事件 子组件: <view> <view v-for="(item,index) in list" :key="index"> <view @tap=“tapOption” :data-index=“index”>{{ item }}</view> </view> </view> <scrpit> export default { methods: { tapOption(e) { /* { “type”: “click”, “timeStamp”: 1731902250741, “target”: { “id”: “”, “attr”: { “dataIndex”: 2 }, “offsetLeft”: 0, “offsetTop”: 0 }, “currentTarget”: { “id”: “”, “attr”: { “dataIndex”: 2 }, “offsetLeft”: 0, “offsetTop”: 0 }, “detail”: {}, “stopPropagation”: “function() { [native code] }” } / console.log(e) // #ifdef APP-NVUE // 执行了这步 var index = e.currentTarget.attr.dataIndex // #endif

} } } </script>

是能解决,但它就是一个bug

以前是 e.currentTarget.attr.dataIndex 现在不知道为啥会变成 e.currentTarget.dataset.index 而且好诡异的事 用整个页面用vue的话 在子组件 现在是获取不了data-*的值

回复 7***@qq.com: 我刚才好像理解错你意思了。其实问题点在于nvue页面引用vue组件,然后vue组件里的条件编译走的却是 nvue平台是吧? 这一点我就不清楚了。 然后获取data-的方式,没看到文档有提到nvue和vue需要区别处理。。。

在uni-app中,nvue页面与vue页面存在一些差异,特别是在处理自定义属性和事件时。针对你提到的问题,我们分别来看如何在nvue中引入vue组件并正确获取data-*属性,以及如何在整页为vue的情况下让子组件的@tap事件获取data-*的数据。

1. 在nvue中引入vue组件并获取data-*属性

在nvue中引入vue组件时,由于nvue和vue的渲染机制不同,直接操作DOM或获取自定义属性可能会遇到问题。一个推荐的解决方案是通过事件机制传递数据。

Vue组件(MyComponent.vue):

<template>
  <view @tap="handleTap">
    <!-- 其他内容 -->
  </view>
</template>

<script>
export default {
  methods: {
    handleTap(event) {
      // 假设data-info是你要传递的数据
      const dataInfo = event.currentTarget.dataset.info;
      this.$emit('tap-event', dataInfo);
    }
  }
}
</script>

nvue页面:

<template>
  <page>
    <stack>
      <frame src="/pages/MyComponent/MyComponent.vue" @tap-event="handleVueTapEvent" />
      <!-- 注意:这里实际上不能直接监听vue组件的事件,需要通过其他方式通信,如全局事件总线 -->
    </stack>
  </page>
</template>

<script>
export default {
  methods: {
    handleVueTapEvent(data) {
      console.log('Vue组件传递的数据:', data);
    }
  },
  mounted() {
    // 假设使用了一个全局事件总线来监听vue组件的事件
    globalEventBus.$on('tap-event', this.handleVueTapEvent);
  },
  beforeDestroy() {
    globalEventBus.$off('tap-event', this.handleVueTapEvent);
  }
}
</script>

注意:由于nvue与vue之间的通信限制,这里示例了通过全局事件总线(需自行实现)来传递事件,实际项目中可能需要根据具体情况调整。

2. 在整页为vue的情况下,子组件@tap事件获取data-*的数据

在纯vue页面中,获取data-*属性相对简单,可以直接在事件处理函数中通过event.currentTarget.dataset访问。

父组件:

<template>
  <MyComponent data-info="someData" @tap="handleChildTap" />
</template>

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

export default {
  components: { MyComponent },
  methods: {
    handleChildTap(event) {
      const dataInfo = event.detail.dataInfo; // 假设子组件通过detail传递了数据
      console.log('子组件传递的数据:', dataInfo);
    }
  }
}
</script>

子组件(MyComponent.vue):

<template>
  <view @tap="handleTap">点击我</view>
</template>

<script>
export default {
  methods: {
    handleTap(event) {
      const dataInfo = event.currentTarget.dataset.info;
      this.$emit('tap', { dataInfo });
    }
  }
}
</script>

这样,父组件就可以正确接收到子组件通过@tap事件传递的data-*数据了。

回到顶部