Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

抖音 27.2.0 在 if 内的 ref 无法获取到 #4554

Closed
zhijiang3 opened this issue Oct 8, 2023 · 5 comments · Fixed by #4555
Closed

抖音 27.2.0 在 if 内的 ref 无法获取到 #4554

zhijiang3 opened this issue Oct 8, 2023 · 5 comments · Fixed by #4555

Comments

@zhijiang3
Copy link

问题描述
抖音 App 版本为 27.2.0 的抖音小程序,v-if 判断的 ref 组件,无法通过 this.$refs 拿到组件实例,如果是抖音App 27.1.0 版本的话,是正常的。

复现步骤

  1. 新建一个 vue 文件:
<!-- src/pages/index/index.vue -->
<template>
  <view>
    <counter v-if="showCounter" ref="counterRef" />

    <button @click="toggle">toggle</button>
    <button @click="add">+</button>
  </view>
</template>

<script>
import counter from '../../components/counter.vue';

export default {
  components: {
    counter,
  },
  data() {
    return {
      showCounter: false,
    }
  },
  methods: {
    toggle() {
      this.showCounter = !this.showCounter;
    },
    add() {
      // 这里 this.$refs 拿不到 counterRef
      this.$refs.counterRef.plus();
    },
  }
}
</script>

<style></style>
  1. 新建 counter 组件
<!-- src/components/counter.vue -->
<template>
  <view>
    {{ counter }}
  </view>
</template>

<script>
export default {
  name: 'counter',
  data() {
    return {
      counter: 0,
    };
  },
  methods: {
    plus() {
      this.counter++;
    },
  },
};
</script>

<style></style>
  1. 编译后,使用 抖音App 27.2.0 版本扫码预览上述代码(一定要真机预览,开发者工具无法重现),点击 toggle 按钮后,点击 + 按钮。

预期结果

点击 + 按钮后,应该能看到数字 0 叠加到 1。

实际结果

报错,refs 拿不到 counterRef。

系统信息:

  • 发行平台: 抖音小程序
  • 操作系统 Android 13
  • uni-app版本
uni-app v3.8.12
uni-app cli v2.0.2-3081220230817001

Environment Info:

  System:
    OS: Windows 10
    CPU: (20) x64 12th Gen Intel(R) Core(TM) i7-12700H
  Binaries:
    Node: 16.17.0 - C:\Program Files\nodejs\node.EXE  
    Yarn: 1.22.19 - C:\Program Files\nodejs\yarn.CMD  
    npm: 8.15.0 - C:\Program Files\nodejs\npm.CMD
  Browsers:
    Edge: 44.18362.449.0
  npmPackages:
    @dcloudio/types: ^3.3.2 => 3.4.0
    @dcloudio/uni-app: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001   
    @dcloudio/uni-app-plus: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-app-plus-nvue:  0.0.1
    @dcloudio/uni-app-plus-nvue-v8:  0.0.1
    @dcloudio/uni-automator: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-cli-i18n: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-cli-shared: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-h5: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001    
    @dcloudio/uni-helper-json: * => 1.0.13
    @dcloudio/uni-i18n: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001  
    @dcloudio/uni-migration: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-360: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-alipay: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-baidu: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-jd: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001 
    @dcloudio/uni-mp-kuaishou: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-lark: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-qq: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001 
    @dcloudio/uni-mp-toutiao: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-vue: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-weixin: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-mp-xhs: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-quickapp-native: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-quickapp-webview: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-stacktracey: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/uni-stat: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001  
    @dcloudio/uni-template-compiler: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/vue-cli-plugin-hbuilderx: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/vue-cli-plugin-uni: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/vue-cli-plugin-uni-optimize: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/webpack-uni-mp-loader: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @dcloudio/webpack-uni-nvue-loader:  0.0.1
    @dcloudio/webpack-uni-pages-loader: ^2.0.2-3081220230817001 => 2.0.2-3081220230817001
    @hap-toolkit/dsl-vue:  0.6.13
    @vue/babel-helper-vue-jsx-merge-props:  1.4.0
    @vue/babel-helper-vue-transform-on:  1.1.5
    @vue/babel-plugin-jsx:  1.1.5
    @vue/babel-plugin-transform-vue-jsx:  1.4.0
    @vue/babel-preset-app:  5.0.8
    @vue/babel-preset-jsx:  1.4.0
    @vue/babel-sugar-composition-api-inject-h:  1.4.0
    @vue/babel-sugar-composition-api-render-instance:  1.4.0
    @vue/babel-sugar-functional-vue:  1.4.0
    @vue/babel-sugar-inject-h:  1.4.0
    @vue/babel-sugar-v-model:  1.4.0
    @vue/babel-sugar-v-on:  1.4.0
    @vue/cli-overlay:  5.0.8
    @vue/cli-plugin-babel: ~5.0.0 => 5.0.8
    @vue/cli-plugin-router:  5.0.8
    @vue/cli-plugin-vuex:  5.0.8
    @vue/cli-service: ~5.0.0 => 5.0.8
    @vue/cli-shared-utils:  5.0.8
    @vue/component-compiler-utils:  3.3.0 (3.3.0)
    @vue/composition-api:  1.7.0
    @vue/devtools-api:  6.0.0-beta.15
    @vue/shared: ^3.0.0 => 3.3.4
    @vue/web-component-wrapper:  1.3.0
    mpvue-page-factory:  1.0.1
    mpvue-template-compiler:  1.0.13
    uni-h5-vue:  2.6.10
    uni-mp-vue:  2.6.10
    vue: >= 2.6.14 < 2.7 => 2.6.14
    vue-hot-reload-api:  2.3.4
    vue-loader:  17.3.0 (15.10.2, 15.10.2, 17.3.0)
    vue-router:  3.0.1
    vue-style-loader:  4.1.3 (4.1.3)
    vue-template-compiler: >= 2.6.14 < 2.7 => 2.6.14 (2.7.14, 2.6.14)      
    vue-template-es2015-compiler:  1.9.1
    vue3:  1.0.0
    vuex: ^3.2.0 => 3.6.2 (3.6.2)
  npmGlobalPackages:
    @vue/cli: Not Found

补充信息

经过排查,发现因为抖音App 27.2.0 版本的 SDKVersion3.0.0,在 initRefs 方法中,对 selectAllComponents API 做了一个兼容处理:

image
image

但是只判断了 minorVersion > 16 ,实际应该判断为 majorVersion > 1 || minorVersion > 16 才对

手动修改代码如下图后,测试正常:

image

@zhijiang3
Copy link
Author

补充一个临时处理方案

  1. 创建 src/plugins/refs-fixed.js 文件,内容如下:
// src/plugins/refs-fixed.js
import Vue from 'vue';

/**
 * @see {@link https://github.com/dcloudio/uni-app/issues/4554}
 */
export function install(vue = Vue) {
  // #ifdef MP-TOUTIAO
  vue.mixin({
    created() {
      initRefs(this);
    },
  });
  // #endif
}

function initRefs(vm) {
  const mpInstance = vm.$scope;
  const refs = {};
  Object.defineProperty(vm, '$refs', {
    get() {
      const $refs = {};
      const components = mpInstance.selectAllComponents('.vue-ref') || [];
      components.forEach((component) => {
        const ref = component.dataset.ref;
        $refs[ref] = component.$vm || toSkip(component);
      });
      const forComponents = mpInstance.selectAllComponents('.vue-ref-in-for') || [];
      forComponents.forEach((component) => {
        const ref = component.dataset.ref;
        if (!$refs[ref]) {
          $refs[ref] = [];
        }
        $refs[ref].push(component.$vm || toSkip(component));
      });
      return syncRefs(refs, $refs);
    },
  });
}

function syncRefs(refs, newRefs) {
  const oldKeys = new Set(...Object.keys(refs));
  const newKeys = Object.keys(newRefs);
  newKeys.forEach((key) => {
    const oldValue = refs[key];
    const newValue = newRefs[key];
    if (
      Array.isArray(oldValue) &&
      Array.isArray(newValue) &&
      oldValue.length === newValue.length &&
      newValue.every((value) => oldValue.includes(value))
    ) {
      return;
    }
    refs[key] = newValue;
    oldKeys.delete(key);
  });
  oldKeys.forEach((key) => {
    delete refs[key];
  });
  return refs;
}

function isObject(obj) {
  return obj !== null && typeof obj === 'object';
}

function toSkip(obj) {
  const OB = '__ob__';
  const SKIP = '__v_skip';
  if (isObject(obj) && Object.isExtensible(obj)) {
    // 避免被 @vue/composition-api 观测
    Object.defineProperty(obj, OB, {
      configurable: true,
      enumerable: false,
      value: {
        [SKIP]: true,
      },
    });
  }
  return obj;
}
  1. main.js 注册:
// src/main.js

// ...

import { install as refsFixedInstall } from '@/plugins/refs-fixed';

refsFixedInstall();

// ...

注意:该方案在抖音 App 1.16.0 或以下版本不适用

@yurj26
Copy link
Contributor

yurj26 commented Oct 11, 2023

感谢反馈,已复现问题。

@yurj26
Copy link
Contributor

yurj26 commented Oct 11, 2023

临时解决方案:替换 文件 到目录 /node_modules/@dcloudio/uni-mp-toutiao/dist

@milo-wjh
Copy link

什么时候发布新版本?

@yurj26
Copy link
Contributor

yurj26 commented Nov 1, 2023

什么时候发布新版本?

更新下HBuilderX,已经修复。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants