NervJS / taro

开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/支付宝/字节跳动/ QQ 小程序/H5/React Native 等应用。 https://taro.zone/
https://docs.taro.zone/
Other
35.55k stars 4.79k forks source link

Vue 组件库中使用了 Vant weapp 的组件,打包后在 Taro 中使用,Vant weapp 组件属性绑定失效 #11312

Closed HyperLife1119 closed 2 years ago

HyperLife1119 commented 2 years ago

相关平台

微信小程序

复现仓库

https://github.com/HyperLife1119/taro-issue 小程序基础库: 2.22.0 使用框架: Vue 3

复现步骤

概要

示例中使用到了一个第三方 vue 组件 list-view,而这个组件中又使用了 vant weapp 的 van-loading 小程序组件。

使用示例:

<template>
  <list-view :loading="true"></list-view>

  <!-- 把下面这行注释打开,属性即可绑定成功 -->
  <!-- <van-loading v-if="false" type size text-size vertical></van-loading> -->
</template>

<script lang="ts">
import { listView } from 'sun-mini-core/components/list-view';

export default {
  components: {
    listView
  }
}
</script>

list-view 组件的模板如下:

<template>
  <scroll-view
    v-bind="$attrs"
    class="list-view"
    :enhanced="true"
    :scroll-y="true"
    :enable-flex="flex"
    :refresher-enabled="refresher && active"
    :refresher-triggered="refresh"
    :refresher-background="bg"
    @refresherrefresh="onRefresh()"
    @scrolltolower="toLower()"
  >
    <slot></slot>
    <view v-if="!data.length" class="dp-flex align-center justify-center" style="height: 85%;">
+     <van-loading v-if="loading" type="spinner" size="85rpx" text-size="30rpx" :vertical="true">正在加载</van-loading>
      <van-empty v-else description="暂无数据" />
    </view>
  </scroll-view>
</template>

可以看到 van-loading 组件是绑定了几个属性的,但实际使用中,这几个属性并没有成功绑定上。

list-view 组件的编译选项:

    template: {
      ssr: false,
      transformAssetUrls: {
        video: ['src', 'poster'],
        'live-player': ['src'],
        audio: ['src'],
        source: ['src'],
        image: ['src'],
        'cover-image': ['src']
      },
      compilerOptions: {
        mode: 'module',
        optimizeImports: true,
        isNativeTag: tag => {
          return [
            'view', 'icon', 'progress', 'rich-text', 'text', 'button', 'checkbox', 'checkbox-group',
            'form', 'input', 'label', 'picker', 'picker-view', 'picker-view-column', 'radio', 'radio-group',
            'slider', 'switch', 'cover-image', 'textarea', 'cover-view', 'movable-area', 'movable-view',
            'scroll-view', 'swiper', 'swiper-item', 'navigator', 'audio', 'camera', 'image', 'live-player',
            'video', 'canvas', 'ad', 'web-view', 'block', 'map', 'open-data', 'custom-wrapper', 'canvas',
            'editor', 'navigation-bar', 'official-account', 'functional-page-navigator'
          ].some(o => o === tag) || tag.startsWith('van-')
        },
      }
    }

重现步骤

编译到微信小程序查看效果

期望结果

第三方 list-view 组件内部的 van-loading 属性能成功绑定 image image

实际结果

第三方 list-view 组件内部的 van-loading 属性没有绑定 image image

环境信息

� Taro v3.4.1

  Taro CLI 3.4.1 environment info:
    System:
      OS: Windows 10
    Binaries:
      Node: 16.13.2 - C:\Program Files\Nodejs\node.EXE
      npm: 8.1.2 - C:\Program Files\Nodejs\npm.CMD
HyperLife1119 commented 2 years ago

问题看起来好像是 taro 没有收集到 第三方 Vue 组件库中的 Vant Weapp 原生组件的属性。需要先在小程序自己的模板上写上这个 Vant 组件有用到哪些属性,然后才能被 taro 收集到。

<!-- 把下面这行注释打开,属性即可绑定成功 -->
  <!-- <van-loading v-if="false" type size text-size vertical></van-loading> -->

能否支持 taro 自动收集 第三方 Vue 组件库中的 Vant Weapp 原生组件的属性呢?

HyperLife1119 commented 2 years ago

list-view 组件编译后的结果:

import { defineComponent, renderSlot, openBlock, createElementBlock, createCommentVNode, mergeProps } from "vue";
import { _ as _export_sfc } from "../plugin-vue_export-helper.js";
const _sfc_main = defineComponent({
  events: ["refresh", "lower"],
  props: {
    refresh: {
      type: Boolean,
      default: false
    },
    flex: {
      type: Boolean,
      default: false
    },
    loading: {
      type: Boolean,
      default: false
    },
    data: {
      type: Array,
      default: []
    },
    refresher: {
      type: Boolean,
      default: true
    },
    bg: {
      type: String,
      default: "#f5f5f5"
    }
  },
  data: () => ({
    active: false
  }),
  methods: {
    onRefresh() {
      this.$emit("refresh");
    },
    toLower() {
      this.$emit("lower");
    }
  },
  mounted() {
    setTimeout(() => this.active = true, 30);
  },
  activated() {
    setTimeout(() => this.active = true, 30);
  },
  deactivated() {
    this.active = false;
  }
});
const _renderSlot = renderSlot, _openBlock = openBlock, _createElementBlock = createElementBlock, _createCommentVNode = createCommentVNode, _mergeProps = mergeProps;
const _hoisted_1 = ["enable-flex", "refresher-enabled", "refresher-triggered", "refresher-background"];
const _hoisted_2 = {
  key: 0,
  class: "dp-flex align-center justify-center",
  style: { "height": "85%" }
};
const _hoisted_3 = {
  key: 0,
  type: "spinner",
  size: "85rpx",
  "text-size": "30rpx",
  vertical: true
};
const _hoisted_4 = {
  key: 1,
  description: "\u6682\u65E0\u6570\u636E"
};
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
  return _openBlock(), _createElementBlock("scroll-view", _mergeProps(_ctx.$attrs, {
    class: "list-view",
    enhanced: true,
    "scroll-y": true,
    "enable-flex": _ctx.flex,
    "refresher-enabled": _ctx.refresher && _ctx.active,
    "refresher-triggered": _ctx.refresh,
    "refresher-background": _ctx.bg,
    onRefresherrefresh: _cache[0] || (_cache[0] = ($event) => _ctx.onRefresh()),
    onScrolltolower: _cache[1] || (_cache[1] = ($event) => _ctx.toLower())
  }), [
    _renderSlot(_ctx.$slots, "default"),
    !_ctx.data.length ? (_openBlock(), _createElementBlock("view", _hoisted_2, [
      _ctx.loading ? (_openBlock(), _createElementBlock("van-loading", _hoisted_3, "\u6B63\u5728\u52A0\u8F7D")) : (_openBlock(), _createElementBlock("van-empty", _hoisted_4))
    ])) : _createCommentVNode("", true)
  ], 16, _hoisted_1);
}
var index = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export { index as listView };
BongBongBang commented 2 years ago

taro对混合开发的支持还比较基础,体验不太好,只能自己根据原依赖组件进行补全

HyperLife1119 commented 2 years ago

最后选择了自行编写插件,使用 modifyComponentConfig 补全组件属性