NervJS / taro

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

【Map组件】marker 上的自定义气泡 customCallout #10625

Open abstain23 opened 2 years ago

abstain23 commented 2 years ago

相关平台

微信小程序

复现仓库

https://github.com/YangJ0605/taro-customcallout-issue 小程序基础库: 2.20.2 使用框架: React

复现步骤

开发者工具上能够正常显示自定义的气泡,并且点击按钮更新值也能更新,但是到真机上点击按钮却无法更新值到视图上

期望结果

期待视图和数据一起更新

实际结果

视图没有更新

环境信息

Taro CLI 3.3.9 environment info:
    System:
      OS: Windows 10
    Binaries:
      Node: 16.10.0 - C:\Program Files\nodejs\node.EXE
      Yarn: 1.22.5 - C:\Program Files (x86)\Yarn\bin\yarn.CMD
      npm: 7.24.0 - C:\Program Files\nodejs\npm.CMD
abstain23 commented 2 years ago

1636541255(1) 1636541323(1)

TheKonka commented 2 years ago

CoverView 真难用, 您的demo 我真机预览 有的时候 直接不显示 !

CyberFei commented 2 years ago

同数据不更新问题

gancao297871092 commented 2 years ago

我的是 真机上连自定义气泡都显示不出来

gancao297871092 commented 2 years ago

改成cover-view也不行啊,文档又更新了一个自定义气泡demo,我cv下来运行到真机上,一样显示不出来

Hilery commented 2 years ago

希望顺手支持一下Vue3。

honlyHuang commented 2 years ago

滴滴出行-小叮当: 不展示的原因就是他的customCallout中展示的值是useState单独定义的, 只要把这个值放到markers里面, 去调用setMarkers就可以变化了

import { Button, CoverView, Map, View } from "@tarojs/components";
import { MapProps } from "@tarojs/components/types/Map";
import { useState } from "react";

import locationPng from "../../image/location.png";

import "./index.scss";

export default function Index() {
  const [markers, setMarkers] = useState<MapProps.marker[]>(() => [
    {
      id: 4,
      latitude: 23.097994,
      longitude: 113.32352,
      iconPath: locationPng,
      width: 36,
      height: 36,
      customCallout: {
        anchorY: -10,
        anchorX: 0,
        display: "ALWAYS"
      }
    }
  ]);

  const [name, setName] = useState(1);

  return (
    <View>
      <Map
        setting={{}}
        markers={markers}
        latitude={23.096994}
        longitude={113.32452}
        style={{ height: "100vh", width: "100vw" }}
      >
        <CoverView slot="callout">
          <CoverView marker-id={4}>
            <CoverView>value:{name}</CoverView>
          </CoverView>
        </CoverView>
      </Map>

      <Button className="btn" onClick={() => setName(v => v + 1)}>
        change data {name}
      </Button>
    </View>
  );
}
LiuJinYang9527 commented 1 year ago

这个问题应该是Taro3.x版本在编译时,把小程序组件的全部属性绑定在了模板中(即使代码中没有写),导致编译出来的CoverView标签都带有marker-id 属性,默认为null,就是这个原因导致了数据不更新以及覆盖物不展示的问题,一开始我是手动给所有的CoverView标签加了markerId='',发现虽然DOM元素中不显示这个属性了,但是还是存在以上问题,最后通过插件重写了Template类的buildStandardComponentTemplate方法暂时解决了,代码如下, 在config/index.jsplugins引入即可。

import { BaseTemplate } from '@tarojs/shared/dist/template'
export default (ctx, options) => {
  ctx.onBuildStart(() => {
    const originFunc = BaseTemplate.prototype.buildStandardComponentTemplate
    BaseTemplate.prototype.buildStandardComponentTemplate = function(comp, level) {
      //针对cover-view特殊处理 生成带有markerId以及不带markerId属性的两个模板并通过if、else进行动态展示
      if (comp.nodeName === 'cover-view') {
        const children = this.getChildren(comp, level)
        const { Adapter } = this
        let res = `
<template name="tmpl_${level}_${comp.nodeName}">
    <${comp.nodeName} ${this.buildAttribute(comp.attributes, comp.nodeName)} ${Adapter.if}="{{i.markerId}}" id="{{i.uid}}">${children}</${comp.nodeName}>
    <${comp.nodeName} ${this.buildAttribute(require('lodash').omit(comp.attributes, 'marker-id'),comp.nodeName)} ${Adapter.else} id="{{i.uid}}">${children}</${comp.nodeName}>
</template>`
        if (typeof this.modifyTemplateResult === 'function') {
          res = this.modifyTemplateResult(res, comp.nodeName, level, children)
        }
        return res
      } else {
        return originFunc.apply(this, arguments)
      }
    }
  })
}

不过这样会导致cover-view的模板代码生成了两份,会增大一定的包体积,但是我感觉可以忽略,一般只有在地图组件中才会使用这个标签。

看官方文档提到过 属性精简 这个功能,如果这个功能实现了,这个问题应该也就没有了,不知道官方还有没有实现这个功能的计划。

lupingW commented 1 year ago

@honlyHuang

lupingW commented 1 year ago

这个问题应该是Taro3.x版本在编译时,把小程序组件的全部属性绑定在了模板中(即使代码中没有写),导致编译出来的CoverView标签都带有marker-id 属性,默认为null,就是这个原因导致了数据不更新以及覆盖物不展示的问题,一开始我是手动给所有的CoverView标签加了markerId='',发现虽然DOM元素中不显示这个属性了,但是还是存在以上问题,最后通过插件重写了Template类的buildStandardComponentTemplate方法暂时解决了,代码如下, 在config/index.jsplugins引入即可。

import { BaseTemplate } from '@tarojs/shared/dist/template'
export default (ctx, options) => {
  ctx.onBuildStart(() => {
    const originFunc = BaseTemplate.prototype.buildStandardComponentTemplate
    BaseTemplate.prototype.buildStandardComponentTemplate = function(comp, level) {
      //针对cover-view特殊处理 生成带有markerId以及不带markerId属性的两个模板并通过if、else进行动态展示
      if (comp.nodeName === 'cover-view') {
        const children = this.getChildren(comp, level)
        const { Adapter } = this
        let res = `
<template name="tmpl_${level}_${comp.nodeName}">
  <${comp.nodeName} ${this.buildAttribute(comp.attributes, comp.nodeName)} ${Adapter.if}="{{i.markerId}}" id="{{i.uid}}">${children}</${comp.nodeName}>
  <${comp.nodeName} ${this.buildAttribute(require('lodash').omit(comp.attributes, 'marker-id'),comp.nodeName)} ${Adapter.else} id="{{i.uid}}">${children}</${comp.nodeName}>
</template>`
        if (typeof this.modifyTemplateResult === 'function') {
          res = this.modifyTemplateResult(res, comp.nodeName, level, children)
        }
        return res
      } else {
        return originFunc.apply(this, arguments)
      }
    }
  })
}

不过这样会导致cover-view的模板代码生成了两份,会增大一定的包体积,但是我感觉可以忽略,一般只有在地图组件中才会使用这个标签。

看官方文档提到过 属性精简 这个功能,如果这个功能实现了,这个问题应该也就没有了,不知道官方还有没有实现这个功能的计划。

大佬666

bluescurry commented 1 year ago

这个问题应该是Taro3.x版本在编译时,把小程序组件的全部属性绑定在了模板中(即使代码中没有写),导致编译出来的CoverView标签都带有marker-id 属性,默认为null,就是这个原因导致了数据不更新以及覆盖物不展示的问题,一开始我是手动给所有的CoverView标签加了markerId='',发现虽然DOM元素中不显示这个属性了,但是还是存在以上问题,最后通过插件重写了Template类的buildStandardComponentTemplate方法暂时解决了,代码如下, 在config/index.jsplugins引入即可。

import { BaseTemplate } from '@tarojs/shared/dist/template'
export default (ctx, options) => {
  ctx.onBuildStart(() => {
    const originFunc = BaseTemplate.prototype.buildStandardComponentTemplate
    BaseTemplate.prototype.buildStandardComponentTemplate = function(comp, level) {
      //针对cover-view特殊处理 生成带有markerId以及不带markerId属性的两个模板并通过if、else进行动态展示
      if (comp.nodeName === 'cover-view') {
        const children = this.getChildren(comp, level)
        const { Adapter } = this
        let res = `
<template name="tmpl_${level}_${comp.nodeName}">
  <${comp.nodeName} ${this.buildAttribute(comp.attributes, comp.nodeName)} ${Adapter.if}="{{i.markerId}}" id="{{i.uid}}">${children}</${comp.nodeName}>
  <${comp.nodeName} ${this.buildAttribute(require('lodash').omit(comp.attributes, 'marker-id'),comp.nodeName)} ${Adapter.else} id="{{i.uid}}">${children}</${comp.nodeName}>
</template>`
        if (typeof this.modifyTemplateResult === 'function') {
          res = this.modifyTemplateResult(res, comp.nodeName, level, children)
        }
        return res
      } else {
        return originFunc.apply(this, arguments)
      }
    }
  })
}

不过这样会导致cover-view的模板代码生成了两份,会增大一定的包体积,但是我感觉可以忽略,一般只有在地图组件中才会使用这个标签。

看官方文档提到过 属性精简 这个功能,如果这个功能实现了,这个问题应该也就没有了,不知道官方还有没有实现这个功能的计划。


您好,我用了这个插件,cover-view 直接不展示了,taro版本是最新的

LiuJinYang9527 commented 1 year ago

我用的Taro版本是3.3.12,可以用这个版本试下或者给一下代码片段 @bluescurry

daiwanxing commented 5 months ago

我找到一个可行的办法,这个 <cover-view /> 标签如果嵌套了很多个,的确在 Taro 里不会触发真机的视图更新(原生我不知道会不会,还没实践),至于具体原因只有问 Taro 开发团队才知道。

然后我在 taro 的 issue 列表检索 <cover-view /> 相关的 issue 时,找到了一个类似的问题 #11461

有位开发者回复道

真机复现了。你这里为什么要嵌套三层 CoverView,我试了一下一层、两层真机都是正常的

于是我尝试将 <cover-view /> 标签只嵌套一个,也就是 slot 节点下只允许嵌套一个 <cover-view /> 标签,代码如下:

<map id="map" class="tecent-map" :longitude="longitude" :latitude="latitude" :markers="markers">
  <cover-view slot="callout" class="custom-callout-wrapper">
      <cover-view class="custom-callout" :marker-id="1">
          {{ count }} 
      </cover-view>
  </cover-view>
</map>

<script>
const count = ref(0);

setInterval(() => {
  count.value++;
}, 1000);
</script>

然后真机调试发现意外的能成功更新气泡的内容。