uni-app中vue3在子组件通过$parent调用父组件方法时H5和小程序存在差异

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

uni-app中vue3在子组件通过$parent调用父组件方法时H5和小程序存在差异

开发环境 版本号 项目创建方式
Windows win10 CLI

示例代码:

父组件:

<template>  
    <view class="content">  
        <aaaaa>  
            <template v-slot:default>  
                <view class="b">111111111</view>  
            </template>  
        </aaaaa>  
    </view>  
</template>  

<script>  
    import aaaaa from './aaaaa.vue'  

    export default {  
        components: {  
            aaaaa,  
        },  
        data() {  
            return { }  
        },  
        onLoad() {  
        },  
        methods: {  
            console() {  
                console.log(1111111111111);  
            },  
        },  
    }  
</script>  

<style></style>

子组件:

<template>  
    <view class="aaaaaa">  
        <slot name="default"></slot>  
    </view>  
</template>  

<script>  
    export default {  
        options: {  
            styleIsolation: 'shared',  
            virtualHost: true,  
        },  
        externalClasses: ['class'],  
        data() {  
            return { }  
        },  
        mounted() {  
            this.$parent.console();    //微信小程序调用成功,H5报this.$parent.console is not a function  
            this.$parent.$parent.console();    //H5调用成功  
        },  
        methods: { },  
    }  
</script>  

<style></style>

操作步骤:

1

预期结果:

this.$parent.console(); 各端调用成功

实际结果:

this.$parent.console(); //微信小程序调用成功,H5报this.$parent.console is not a function this.$parent.$parent.console(); //H5调用成功

bug描述:

当我在子组件使用this.$parent调用父组件的方法时,H5和小程序有差异。

h5: this.$parent.$parent.xxxx()

微信小程序: this.$parent.xxxx()


4 回复

参考文档注意事项

H5端 view、text 等内置标签是以 Vue 组件方式实现,$parent 会获取这些到内置组件,导致的问题是 this.$parent 与其他平台不一致,解决方式是使用 this.$parent.$parent 获取或自定义组件根节点由 view 改为 div。


子组件:

问题还是存在的

uni-app 中,使用 Vue 3 开发时,通过 $parent 调用父组件方法在 H5 和小程序平台上的行为确实存在差异。这种差异主要是由于不同平台的运行机制和实现方式不同所导致的。

1. H5 平台

在 H5 平台上,uni-app 使用的是标准的 Vue.js 运行时环境。因此,$parent 的行为与 Vue.js 官方文档中描述的一致。你可以通过 $parent 直接访问父组件的实例,并调用其方法。

<template>
  <button [@click](/user/click)="callParentMethod">调用父组件方法</button>
</template>

<script setup>
const callParentMethod = () => {
  if (parent.$parent) {
    parent.$parent.parentMethod();
  }
};
</script>

2. 小程序平台

在小程序平台上,uni-app 使用的是小程序的原生组件系统,Vue 组件的实例与小程序组件的实例并不完全一致。因此,$parent 的行为可能会有所不同。

在小程序平台上,$parent 可能无法直接访问到父组件的 Vue 实例,或者访问到的对象并不是你期望的父组件实例。这会导致在小程序平台上通过 $parent 调用父组件方法时出现错误或无法正常工作。

解决方案

为了在不同平台上保持一致性,建议使用 provide/inject事件通信 的方式来在父子组件之间进行通信,而不是直接依赖 $parent

使用 provide/inject

在父组件中使用 provide 提供方法,在子组件中使用 inject 注入方法。

<!-- 父组件 -->
<template>
  <ChildComponent />
</template>

<script setup>
import { provide } from 'vue';
import ChildComponent from './ChildComponent.vue';

const parentMethod = () => {
  console.log('父组件方法被调用');
};

provide('parentMethod', parentMethod);
</script>
<!-- 子组件 -->
<template>
  <button [@click](/user/click)="callParentMethod">调用父组件方法</button>
</template>

<script setup>
import { inject } from 'vue';

const parentMethod = inject('parentMethod');

const callParentMethod = () => {
  if (parentMethod) {
    parentMethod();
  }
};
</script>

使用事件通信

在子组件中通过 $emit 触发事件,在父组件中监听事件并执行相应的方法。

<!-- 父组件 -->
<template>
  <ChildComponent @call-parent-method="parentMethod" />
</template>

<script setup>
const parentMethod = () => {
  console.log('父组件方法被调用');
};
</script>
<!-- 子组件 -->
<template>
  <button [@click](/user/click)="callParentMethod">调用父组件方法</button>
</template>

<script setup>
const emit = defineEmits(['call-parent-method']);

const callParentMethod = () => {
  emit('call-parent-method');
};
</script>
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!