我知道有一个google maps vue库,但我在代码库中工作,它已经创建了一些类似的组件。
特别是,我有一个组件在vue中包裹rich-marker,暴露了一个在地图上呈现为富标记的插槽。
为了完成这项工作,我需要向Google API提供div
,并且我希望此div
的内容能够反映slot
的内容。使用渲染函数似乎部分工作如下(粗略地):
render(createElement){
let content = createElement('div', this.$slots.default);
this._marker = new RichMarker({
content: content,
map: this.map
});
return content;
}
但它有时会导致问题,因为Vue控制下的DOM节点正在树上移动(谷歌地图将它们放在任何需要的地方)。这由以下错误显示:
DOMException: Failed to execute 'insertBefore' on 'Node':
The node before which the new node is to be inserted is not a child of this node.
为了避免这种情况,我可以考虑几个选项:
$slots.default
VNode
转换为实际的DOM节点,然后将其提供给Google(并使渲染函数返回虚拟空div
)。innerHTML
复制到Google的新div
。我无法找到任何可以让我选择的东西(1.)。有谁知道Vue中是否有未记录的部分可以让我这样做?
我确实尝试了选项(2.),但update
生命周期事件似乎没有做我需要的事情,因为当插槽内容发生变化时它没有触发。我也不确定在真正的DOM渲染后是否可以保证触发。
我也尝试过选项(3.)但是与选项(2.)有类似的问题。实际上,我不确定选项(3.)是否真的有用,因为Vue需要改变与插槽相关的节点以及标记组件的节点。
更新 我设法最终做出选项(3.)的工作。渲染函数现在看起来大致如下:
render(createElement){
this._otherEl = this._otherEl || document.createElement('div');
let elInner = createElement('div', this.$slots.default);
let el = createElement('div', {}, [elInner]);
if(this.$el && this.$el.firstChild && this._otherEl.firstChild !== this.$el.firstChild){
this._otherEl.firstChild && this._otherEl.removeChild(this._otherEl.firstChild);
this._otherEl.appendChild(this.$el.firstChild);
}
this.marker = new RichMarker({
content: this._otherEl,
map: this.map
});
return el;
}
marker
需要在组件的data
中声明(由于某些原因我没有进一步调查)。