uni-app 微信小程序无法通过$slots获取插槽节点,App和H5无法通过$parent传值给父节点

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

uni-app 微信小程序无法通过$slots获取插槽节点,App和H5无法通过$parent传值给父节点

测试过的手机

红米k40,ios模拟器,iphone7p

示例代码

  • 微信小程序vue2获取插槽节点:
    this.$slots.default
  • 微信小程序vue3获取插槽节点
    this.$slots.default()
  • H5、APP通过$parent向父节点传值:
    • 子节点:
      this.$parent.a = this
    • 父节点输出为undefined

操作步骤

  • 微信小程序vue2获取插槽节点:
    this.$slots.default
  • 微信小程序vue3获取插槽节点
    this.$slots.default()
  • H5、APP通过$parent向父节点传值:
    • 子节点:
      this.$parent.a = this
    • 父节点输出为undefined

预期结果

  • this.$slots.default正常获取插槽节点列表
  • this.$parent.a正常获取子节点信息(此写法参照uni-form和uni-form-item)

实际结果

  • this.$slots.default 值为ture而不是列表
  • this.$parent.a值为undefined而不是子节点的this

bug描述

  1. 微信小程序通过 $slots 获取到的 default 值为 true,而不是插槽节点列表。
  2. APP和H5插槽节点通过 $parent.a 对父节点的 a 进行复制时,父节点取到 a 的值为 undefined

11 回复

刚好看到,帮下你吧 建议不要用这种方式。vue3同时也取消了$children的。父级是可以取到,但它的父级并不一定是你认为的父级,它是按层级往上冒泡找到父点的。解决方案: 如何找父节点?: 1、父节点定义标识。 2、子节点通过冒泡循环获得父节点,执行找到标识即为离他最近的父节点。 如何获取子节点? 因为vue3取消了$children,当然在h5可以$slot取得,但在跨平台中这种方式,坚决不要使用。 解决方案: 1、父节点定义方法 2、子节点渲染期,找到父节点,然后执行父节点方法向其报告或者推送子节点信息,父节点缓存它的所有子组件。 3、子组件注销也要向父报告,让父组件从缓存中删除该节点,以同步信息。 这样的方案好处是: 1、全平台兼容。 2、父子组件通信方便,方便处理。 你可以下载我的vue3组件库学习这种方案。

你理解错我的意思了,我是通过$parent把子节点push个父节点,懂?不是直接获取子节点

回答之前先看清下问题,但还是感谢你的回答,不过有点不好就是广告,个人有点讨厌哈

另外就是,通过$parent吧子节点推送给父节点小程序中是可行的,我也是用这种方案,但h5和app是不行的,官方的uni-form也是存在这种问题

你们俩真逗,我来看看

快上传个demo来,看看你们俩谁说的有理

回复 呆狗的一生: 那人家在我身上打个个打广告的标签,你说无语,好心当驴踢。

官方的uni-form和uni-form-item就是demo,这个就出现我说的这种情况,子组件把自身实例push进父组件进行缓存,在小程序这种方法是可以行的通的,但在h5里面只能通过获取插槽的方式

回复 云逻星空: 我本不想与你作任何讨论的,但本着我善良我还是再帮你下: 使用inject 和provide,前面说的parent推送和销毁,只是告诉父组件你的存在。 1、子获取父的数据,使用inject,还可以响应式,并且可监听父组件的数据是否修改。 2、子修改父数据,通过parent方法。 3、父修改子数据,通过provide向下发送修改指令参数,子监听后进行判断是修改还是其它任意命令。 3、父读取子数据,使用parent的方法向父推送即可。 通过以上方法你将:全平台兼容。 以后对帮你的人客户气点,至少要尊重,不要那么傲娇!!!

uni-app 开发中,微信小程序、App 和 H5 平台的行为确实存在一些差异,尤其是在处理插槽和父子组件通信时。以下是一些常见问题的解决方案:

1. 微信小程序无法通过 $slots 获取插槽节点

在微信小程序中,$slots 的行为与 Vue.js 中的 $slots 有所不同。微信小程序的插槽机制是基于 WXML 的,而不是 Vue.js 的插槽机制。因此,直接使用 $slots 可能无法获取到插槽节点。

解决方案:

  • 使用 slot 属性:在微信小程序中,你可以使用 slot 属性来定义插槽内容,并在父组件中通过 this.selectComponentthis.selectAllComponents 来获取插槽节点。

    <!-- 父组件 -->
    <view>
      <child-component>
        <view slot="header">Header Content</view>
        <view slot="footer">Footer Content</view>
      </child-component>
    </view>
    
    <!-- 子组件 child-component -->
    <view>
      <slot name="header"></slot>
      <slot name="footer"></slot>
    </view>
  • 使用 ref 获取子组件实例:在父组件中,你可以通过 ref 获取子组件的实例,然后通过子组件的方法或属性来获取插槽内容。

    <!-- 父组件 -->
    <view>
      <child-component ref="child"></child-component>
    </view>
    
    <script>
    export default {
      mounted() {
        const child = this.$refs.child;
        // 通过 child 的方法或属性获取插槽内容
      }
    }
    </script>

2. App 和 H5 无法通过 $parent 传值给父节点

uni-app 中,$parent 在 App 和 H5 平台上的行为可能与预期不一致,尤其是在复杂的组件嵌套结构中。

解决方案:

  • 使用 provideinjectprovideinject 是 Vue.js 提供的一种跨层级组件通信的方式,可以在父组件中提供数据,然后在子组件中注入数据。

    // 父组件
    export default {
      provide() {
        return {
          parentData: this.someData
        };
      },
      data() {
        return {
          someData: 'Hello from parent'
        };
      }
    }
    
    // 子组件
    export default {
      inject: ['parentData'],
      mounted() {
        console.log(this.parentData); // 输出: Hello from parent
      }
    }
  • 使用事件通信:通过 $emit$on 实现父子组件之间的通信。

    <!-- 父组件 -->
    <view>
      <child-component @custom-event="handleEvent"></child-component>
    </view>
    
    <script>
    export default {
      methods: {
        handleEvent(data) {
          console.log(data); // 输出: Data from child
        }
      }
    }
    </script>
    
    <!-- 子组件 -->
    <view>
      <button @click="sendData">Send Data</button>
    </view>
    
    <script>
    export default {
      methods: {
        sendData() {
          this.$emit('custom-event', 'Data from child');
        }
      }
    }
    </script>
  • 使用全局状态管理:对于复杂的应用,可以考虑使用 Vuex 或 Pinia 等状态管理工具来管理组件之间的共享状态。

    // store.js
    import { createStore } from 'vuex';
    
    const store = createStore({
      state: {
        sharedData: 'Shared Data'
      },
      mutations: {
        updateData(state, newData) {
          state.sharedData = newData;
        }
      }
    });
    
    export default store;
    
    // 父组件
    <script>
    import { mapState } from 'vuex';
    
    export default {
      computed: {
        ...mapState(['sharedData'])
      }
    }
    </script>
    
    // 子组件
    <script>
    export default {
      methods: {
        updateSharedData() {
          this.$store.commit('updateData', 'New Shared Data');
        }
      }
    }
    </script>
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!