uni-app 钉钉小程序上动态添加的组件获取inject中的变量为undefined

uni-app 钉钉小程序上动态添加的组件获取inject中的变量为undefined

开发环境 版本号 项目创建方式
Windows 10 HBuilderX

产品分类:uniapp/小程序/阿里

示例代码:

Radio组件

<template>  
    <view class="checkbox" @click="check">  
        <view class="iconfont">{{ checked?'&#xe763;':'&#xe6d7;' }}</view>  
        <view class="text">  
            <slot />  
        </view>  
    </view>  
</template>  

<script>  
    export default {  
        props: {  
            checked: {  
                default: false,   
            },  
            value: {  
                default: '',  
            },   
        },  
        model: {  
            props: 'checked',  
            event: 'onChange'  
        },  
        inject: {  
            radioGroupContext: { default: undefined },  
        },  
        methods: {  
            check(e) {  
                console.log(this.radioGroupContext)  
                e.target.checked = false;  
                e.target.value = undefined;  
                if (this.radioGroupContext && this.radioGroupContext.onRadioChange) {  
                    this.radioGroupContext.emptyAll((node) => {  
                        node.$emit('update:checked', e);  
                    });  
                }  

                e.target.checked = !this.checked;  
                e.target.value = this.value;  
                this.$emit('onChange', e);  
                this.$emit('update:checked', e);  
                if (this.radioGroupContext && this.radioGroupContext.onRadioChange) {  
                    this.radioGroupContext.onRadioChange(e);  
                }  
            },  
        }  
    }  
</script>  

<style lang="scss" scoped>  
.checkbox{  
    display: inline-flex;  
    align-items: center;  
    font-size: 30rpx;  
    line-height: 0;  
    .iconfont{  
        font-size: 32rpx;  
        color: $blue;  
    }  
    .text{  
        margin-left: 10rpx;  
        color: $black5;  
    }  
}  
</style>  

RadioGroup组件

<template>  
    <view class="checkbox-group">  
        <slot />  
    </view>  
</template>  

<script>  
    export default {  
        name:"RadioGroup",  
        provide() {  
            return {  
                radioGroupContext: this,  
            };  
        },  
        data() {  
            return {  

            };  
        },  
        methods: {  
            onRadioChange(e) {  
                this.$emit('onChange', e)  
            },  
            emptyAll(callback) {  
                this.$children.forEach(node => {  
                    callback && callback(node)  
                })  
            }  
        }  
    }  
</script>  

<style lang="scss" scoped>  
.checkbox-group{  
    width: 100%;  
    display: flex;  
    justify-content: flex-end;  
}  
</style>

使用示例Demo

<template>  
    <view class="container">  
        <view class="form-contrl"  v-for="(item,i) in list" :key="i">  
            <MtRadioGroup class="ck-group" @onChange="onRadioChange">  
                <MtRadio :checked="item.isPlay" :value="true">是</MtRadio>  
                <MtRadio class="ck-item" :checked="!item.isPlay" :value="false">否</MtRadio>  
            </MtRadioGroup>  
        </view>  
    </view>  
</template>  

<script>  
    import MtRadioGroup from '../../components/RadioGroup/RadioGroup.vue'  
    import MtRadio from '../../components/Radio/Radio.vue'  
    import MtButton from '../../components/Button/Button.vue'  
export default {  
    components:{  
        MtRadioGroup,  
        MtRadio,  
                MtButton,  
    },  
    data() {  
        return {  
            list: [  
                {isPlay: true},  
                {isPlay: true},  
            ],  
        };  
    },  
    onLoad() {  
    },  
    methods: {  
        onRadioChange(e) {  
            console.log(e)  
        },  
        add() {  
            this.list.push({isPlay: true});  
        },  
    }  
};  
</script>  

<style lang="scss" scoped>  
.ck-group {  
    .ck-item {  
        margin-left: 40rpx;  
    }  
}  
.card{  
    height: 88rpx;  
    line-height: 88rpx;  
    padding: 30rpx;  
    border: 1px solid red;  
}  
</style>  

更多关于uni-app 钉钉小程序上动态添加的组件获取inject中的变量为undefined的实战教程也可以访问 https://www.itying.com/category-93-b0.html

1 回复

更多关于uni-app 钉钉小程序上动态添加的组件获取inject中的变量为undefined的实战教程也可以访问 https://www.itying.com/category-93-b0.html


在钉钉小程序中动态添加组件时,inject 获取为 undefined 通常是由于组件实例化时机问题导致的。钉钉小程序与 Vue 的响应式机制在动态渲染时存在差异。

问题分析:

  1. 动态添加的 MtRadio 组件在初始化时,其父组件 MtRadioGroup 可能已完成 provide 的初始化,但子组件的 inject 未能正确接收到上下文。
  2. 钉钉小程序的渲染层与逻辑层通信机制可能导致 provide/inject 在动态组件中响应不及时。

解决方案:

  1. 使用 $parent 替代 inject(推荐): 在 MtRadio 组件中,通过 this.$parent 直接访问父组件实例,确保能获取到 radioGroupContext 方法:

    <script>
    export default {
      methods: {
        check(e) {
          const parent = this.$parent; // 直接获取父组件实例
          if (parent && parent.onRadioChange) {
            parent.emptyAll((node) => {
              node.$emit('update:checked', e);
            });
          }
          // 其余逻辑不变
        }
      }
    }
    </script>
    
  2. 延迟注入检查: 在 MtRadiomounted 生命周期中重新检查 inject 值,若为 undefined 则通过 $parent 回退:

    <script>
    export default {
      mounted() {
        if (!this.radioGroupContext) {
          this.radioGroupContext = this.$parent;
        }
      }
    }
    </script>
回到顶部