ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ToolJet Map 组件深度解析:属性、事件、组件特定动作与源码级实现原理

ToolJet Map 组件深度解析:属性、事件、组件特定动作与源码级实现原理 ToolJet Map 组件深度解析属性、事件、组件特定动作与源码级实现原理【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet本文以 ToolJet 的 Map地图组件为主线完整覆盖其属性配置、事件体系、组件特定动作CSA、暴露变量与样式控制并结合frontend/src/AppBuilder/Widgets/Map/下的实际源码剖析其底层基于react-google-maps/api的实现机制、动态值fx解析流程以及自托管部署时GOOGLE_MAPS_API_KEY环境变量的配置方式。读完本文你将能够独立配置并编程化控制 Map 组件在业务应用中展示商家、门店或用户位置并通过事件与变量实现地图交互闭环。一、组件定位与典型场景Map 组件用于在应用中显示一张地图支持展示或选择单个/多个地理位置。文档中给出的典型场景包括展示企业、门店或餐厅的位置展示用户在地图上的位置以及允许终端用户与地图界面交互、点击选取兴趣点。从源码结构看Map 是 ToolJet 前端 WidgetManager 中注册的一个标准组件。其注册配置文件 map.js 声明了组件元数据其中默认尺寸为宽 16 列、高 420 像素defaultSize: { width: 16, height: 420 }组件标识为Map描述为 Display map locations。组件的实际渲染逻辑位于 Map.jsx。二、自托管部署前提配置 Google Maps API Key原文档明确提示若使用 ToolJet 自托管self-hosted版本必须将 Google Maps API key 配置为环境变量否则地图无法正常加载。这一点在源码中得到印证Map.jsx 中地图脚本通过如下方式加载LoadScript googleMapsApiKey{window.public_config.GOOGLE_MAPS_API_KEY} libraries{[places}} GoogleMap ... / /LoadScript即组件依赖window.public_config.GOOGLE_MAPS_API_KEY这一前端全局配置项来初始化 Google Maps JS SDK并同时加载places库Places 库是地点搜索能力的前提详见第四节。环境变量GOOGLE_MAPS_API_KEY的官方说明见 env-vars.md 中的 Google maps configuration (optional) 章节variabledescriptionGOOGLE_MAPS_API_KEYGoogle maps API key三、Properties 属性详解Map 组件提供 5 个专属属性。以下在继承原文档说明的基础上结合 map.js 中的配置补充了默认值与校验规则。属性说明期望取值Initial location应用初始加载时的默认位置。包含latitude和longitude键值对的对象。例{{ {lat: 40.7128, lng: -73.935242} }}。Default markers地图上应显示的标记点数量即初始标记点集合。包含坐标的对象数组。例{{ [{lat: 40.7128, lng: -73.935242}, {lat: 40.7128, lng: -73.935242}] }}。Polygon points使用给定坐标在地图上创建多边形。包含坐标的对象数组。例{{ [{lat: 40.7128, lng: -73.935242}, {lat: 40.7128, lng: -73.935242}] }}。Add new markers点击地图时在对应位置添加新标记。默认On。切换为off可禁用点击加标记行为。点击fx可动态设置{{true}}/{{false}}。Search for places启用后在地图左上角显示地点搜索框。默认On。切换为off可禁用搜索框。点击fx可动态设置{{true}}/{{false}}。源码层面有三个值得注意的细节前三个属性均为code类型编辑器。map.js 中initialLocation、defaultMarkers、polygonPoints均配置为type: code、mode: javascript校验 schema 为union即对象或对象数组schemas: [{ type: array, element: { type: object } }, { type: object }]。这意味着这三个字段不仅接受静态坐标对象还支持 fx 动态表达式例如{{ JSON.parse(query1.data) }}之类的查询结果。两个开关属性的默认值均为trueaddNewMarkers与canSearch的defaultValue均为true与文档默认 On的说明一致。渲染时的兜底逻辑Map.jsx 中initialLocation缺失时回退到{ lat: 0, lng: 0 }addNewMarkers与canSearch缺失时回退到falsepolygonPoints与defaultMarkers缺失时回退到空数组。多边形渲染的附加条件Map.jsx 中仅当polygonPoints.length 1时才会渲染Polygon且样式是硬编码的——描边色#4d72fa、线宽 2、填充色#4d72fa、填充不透明度 0.5因此多边形外观不支持属性级自定义。四、Events 事件体系事件名触发时机On bounds change地图可视边界bounding area发生变化后触发此时bounds暴露变量已更新。On create marker向地图添加新标记点时触发。On marker click用户点击地图上任意标记点时触发。On polygon click用户点击地图上的多边形时触发。这四个事件在 map.js 的events段注册并与 Map.jsx 中的四处fireEvent调用一一对应onBoundsChange由 handleBoundsChange 触发绑定在地图的onDragEnd上即用户拖拽地图结束。该函数通过gmap.getBounds()取出northEast/southWest两个角点连同新的center一并写入暴露变量最后才fireEvent(onBoundsChange)——这保证了事件处理函数内读取bounds、center时拿到的一定是新值。onCreateMarker由 handleMapClick 触发。若canAddNewMarkers为假则直接返回否则从点击事件的e.latLng中取出经纬度追加进markers状态、更新暴露变量再触发事件。onMarkerClick由 handleMarkerClick 触发先将被点击的标记写入selectedMarker暴露变量再触发事件。onPolygonClick直接绑定在Polygon的onClick上。关于 ToolJet 全部可用 Actions 的更多信息可参考 Actions 参考文档以及在 RunJS 查询中执行动作的用法见 run-action-from-runjs.md。五、Component Specific ActionsCSAMap 组件当前对外暴露一个组件特定动作可在任意事件处理函数中通过 RunJS 查询编程化调用动作说明调用方式setLocation通过经度、纬度参数在地图上设置标记点位置。在 RunJS 查询中执行component.map1.setLocation(40.7128, -73.935242)。动作定义见 map.jshandle为setLocation接收latLatitude与lngLongitude两个参数。其实现机制在 Map.jsx 的初始化useEffect中组件挂载时通过setExposedVariables将一个闭包函数注入到组件的暴露变量对象上const exposedVariables { setLocation: async function (lat, lng) { if (lat lng) setMapCenter(resolveWidgetFieldValue({ lat, lng })); }, center: addMapUrlToJson(resolvedCenter), markers: defaultMarkers, };也就是说setLocation本质上是一个被挂到components.id命名空间下的异步函数它经resolveWidgetFieldValue解析参数因此参数位置同样支持 fx 表达式再调用setMapCenter把地图中心平移到目标坐标。六、Exposed Variables 暴露变量暴露变量用于从组件中读取运行时数据完整清单如下变量说明访问方式center持有纬度、经度及 Google Maps URL 三个值。center.latMap 组件上标记点的纬度值。{{components.map1.center.lat}}center.lngMap 组件上标记点的经度值。{{components.map1.center.lng}}center.googleMapUrl中心标记点位置的 Google Maps URL。{{components.map1.center.googleMapUrl}}markers仅在启用add new markers属性后持有值每个标记为含lat、lng键的对象。{{components.map1.markers[1].lat}}selectedMarker用户所选标记点构成的对象。bounds由西南角与东北角两点构成的矩形地图可视范围。bounds.northEast矩形东北角的经纬度。{{components.map1.bounds.northEast.lat}}或{{components.map1.bounds.northEast.lng}}bounds.southWest矩形西南角的经纬度。{{components.map1.bounds.southWest.lat}}或{{components.map1.bounds.southWest.lng}}源码印证了各变量的写入时机与结构center / googleMapUrladdMapUrlToJson 在中心坐标对象上追加一个可直接打开的 URL 字段https://www.google.com/maps/?api1map_actionmapcenterlat,lng。center在地图onLoad、拖拽结束handleBoundsChange以及initialLocation变化时都会刷新见 Map.jsx。markers初始值来自defaultMarkers属性Map.jsx 中监听defaultMarkers变化同步状态用户点击地图新增标记后handleMapClick会即时将最新数组写入markers暴露变量。selectedMarkerhandleMarkerClick中执行setExposedVariable(selectedMarker, markers[index])即当前点击索引对应的完整标记对象。boundshandleBoundsChange中由getBounds().getNorthEast().toJSON()与getSouthWest().toJSON()构造故northEast/southWest各含lat、lng两个子字段。一个实用的组合用法在onBoundsChange事件处理中读取components.map1.bounds即可在用户平移/缩放地图后用边界坐标作为参数去执行一条查询例如只加载当前可视范围内的门店数据。七、动态值解析与交互实现原理7.1 fx 动态值的统一解析入口Map 属性中所有{{ ... }}表达式最终都经过 resolveWidgetFieldValue 解析export function resolveWidgetFieldValue(prop, _default [], customResolveObjects {}) { const widgetFieldValue prop; try { const state {}; // getCurrentState(); return resolveReferences(widgetFieldValue, state, _default, customResolveObjects); } catch (err) { console.log(err); } return widgetFieldValue; }在 Map.jsx 中可以看到该函数的三类典型用法解析initialLocation得到地图初始中心第 48 行useState(() resolveWidgetFieldValue(center))解析styles.visibility得到可见性布尔值第 41 行解析setLocation的入参坐标第 150 行。解析失败时回退原值并打印日志保证组件不会因表达式异常而白屏。7.2 地图交互细节从 Map.jsx 的渲染结构看地图实例GoogleMap固定zoom{12}关闭街景与地图类型控件streetViewControl: false、mapTypeControl: false允许拖拽draggable: true。地点搜索仅当canSearch为真时渲染Autocomplete第 196-204 行用户选定搜索结果后onPlaceChanged会把地图中心移动到所选地点的geometry.location并顺带触发一次handleBoundsChange刷新bounds/center并触发onBoundsChange事件。搜索框的占位文本走 i18n 翻译键globals.search。标记点markers数组逐项渲染为Marker支持可选的label字段点击回调携带索引以便写入selectedMarker。深色模式当darkMode为真时应用 styles.js 中的darkModeStylesGoogle Maps 主题化样式集styles.scss 则隐藏了 Places 自动补全的默认面板.pac-container { display: none !important; }因为组件使用的是onPlaceChanged回调而非下拉面板交互。编辑态装饰编辑器画布中地图上叠加了一个中心大头针图标assets/images/icons/marker.svg作为组件可视化标记仅用于设计态辨识。八、通用能力Devices 与 StylesDevices设备可见性属性说明期望取值Show on desktop组件在桌面视图中可见。可用开关按钮设置或点击fx输入逻辑表达式动态控制。Show on mobile组件在移动视图中可见。可用开关按钮设置或点击fx输入逻辑表达式动态控制。源码中对应mapConfig.others段的两个 toggle 属性 showOnDesktop / showOnMobile注意组件定义里二者的出厂默认值分别为{{true}}与{{false}}map.js即新建的 Map 组件默认只在桌面端显示。General — TooltipTooltip 用于在用户鼠标悬停组件时展示附加说明信息一旦设置了 Tooltip 值悬停时即显示指定字符串。Styles样式属性说明期望取值Visibility开关组件的可见性。点击旁边的fx按钮可编程修改。设为{{false}}时应用发布后组件不可见。默认{{true}}。Disable默认off切换为on时锁定组件、使其不可交互。也可通过fx按钮编程设置。设为{{true}}后组件被锁定不可用。默认{{false}}。Box shadow提供 X、Y、Blur、Spread 与 Color 值为组件添加阴影效果。也可通过fx按钮编程设置。例{{x: 0, y: 0, blur: 0, spread: 0, color: #000000}}。源码中visibility直接决定外层容器display: noneMap.jsx 中style{{ height, display: parsedWidgetVisibility ? : none, boxShadow: styles.boxShadow }}disabledState则写入data-disabled属性供编辑器渲染锁定态boxShadow原样作用于容器内联样式。九、小结与延伸阅读Map 组件通过属性位置/标记/多边形/开关 事件边界/标记/多边形交互 CSAsetLocation 暴露变量center/markers/selectedMarker/bounds四层机制构成完整的地图交互闭环其底层由react-google-maps/api驱动所有动态值统一经resolveWidgetFieldValue解析。自托管环境下务必先配置GOOGLE_MAPS_API_KEY环境变量。相关路径一览组件文档源文件docs/docs/widgets/map.md组件注册与默认值frontend/src/AppBuilder/WidgetManager/widgets/map.js组件渲染实现frontend/src/AppBuilder/Widgets/Map/Map.jsx深色模式样式frontend/src/AppBuilder/Widgets/Map/styles.js环境变量说明docs/docs/setup/env-vars.mdActions 参考目录docs/docs/actions/【免费下载链接】ToolJetOpen-source foundation of ToolJet AI - the enterprise app generation platform for internal tools, dashboards, business applications, workflows and AI agents. Build visually, from a prompt, or from Claude Code, Codex and Cursor over MCP 项目地址: https://gitcode.com/GitHub_Trending/to/ToolJet创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表