Vue3同一组件多次复用仅首个实例的D3功能正常问题求助
问题根源
你的代码中所有D3选择器都使用了全局标签选择select('svg')、select('svg g'),这类选择器会默认匹配整个文档中第一个符合条件的DOM节点,所以无论你实例化多少个组件,所有D3操作都会集中到第一个组件的SVG节点上,后续组件自然没有内容生成。同时你代码中svg.append("svg")属于冗余操作,template里已经声明了SVG节点,不需要重复追加。
修复后可正常复用的代码
<template> <div class="fill-100"> <svg ref="svgRef" width="400" height="667"> <g ref="gRef"></g> </svg> </div> </template> <script> import { ref, onMounted } from "@vue/runtime-core"; import { select, zoom } from "d3"; export default { name: "SldSvgD3", props: ["id"], setup() { const svgRef = ref(null); // 直接绑定当前组件内的g节点,避免全局查询 const gRef = ref(null); onMounted(() => { // 所有操作都限定在当前组件的节点范围内 const currentSvg = select(svgRef.value); const currentG = select(gRef.value); let data = [], width = 400, height = 667, numPoints = 100; const zoom3 = zoom() .on('zoom', handleZoom); function handleZoom(e) { currentG.attr('transform', e.transform); } function initZoom() { // 仅给当前组件的SVG绑定缩放事件 currentSvg.call(zoom3); } function updateData() { data = []; for(let i=0; i<numPoints; i++) { data.push({ id: i, x: Math.random() * width, y: Math.random() * height }); } } function update() { // 仅在当前组件的g节点下生成圆点 currentG .selectAll('circle') .data(data) .join('circle') .attr('cx', d => d.x) .attr('cy', d => d.y) .attr('r', 3); } initZoom(); updateData(); update(); }); return { svgRef, gRef } } } </script> <style lang="scss"> .fill-100{ width: 100%; height: 100%; } </style>
核心修改说明
- 新增
gRef直接绑定当前组件内的g节点,所有DOM操作都限定在当前组件的节点范围内,不会跨实例影响其他组件 - 删除冗余的
svg.append("svg")操作 - 缩放事件仅绑定到当前组件的SVG节点,不会和其他实例的缩放逻辑冲突
内容的提问来源于stack exchange,提问作者patrpok
相关产品推荐
相关产品推荐

