使用D3.js与Polymer开发响应式时间轴时获取DOM元素报错求助
Hey there! No worries about your English at all—let's work through this issue step by step 😊
The problem you're running into is tied to how Polymer uses Shadow DOM to encapsulate component markup. When you try to use document.getElementById("chart") directly, it can't find the element because that <div> lives inside your Polymer component's isolated Shadow DOM tree, not the main document's DOM.
Here are the fix steps you can take:
1. Use Polymer's Built-in Element References
Polymer automatically creates references to elements with IDs in your component template, storing them in the this.$ object. This is the simplest way to access your chart element.
Update your component's script section to fetch the element inside a lifecycle hook like connectedCallback() (or ready() for older Polymer versions):
<script> class MyTimeline extends Polymer.Element { static get is() { return 'my-timeline'; } connectedCallback() { super.connectedCallback(); // Always call the parent method first! // Grab the chart element using Polymer's automatic reference const chartElement = this.$.chart; if (chartElement) { // Now initialize your D3.js timeline here console.log("Successfully found chart element:", chartElement); // Example D3 setup: // d3.select(chartElement) // .append("svg") // .attr("width", "100%") // .attr("height", 300); } else { console.error("Could not locate the chart element"); } } } customElements.define(MyTimeline.is, MyTimeline); </script>
2. Ensure Your Markup Lives Inside the Component Template
Double-check that your <section> and <div id="chart"> are wrapped inside the <template> tag of your my-timeline component. If they're outside the template, they won't be part of the component's Shadow DOM and the this.$ reference won't work:
<dom-module id="my-timeline"> <template> <style> /* Add your responsive styling here */ section { width: 100%; display: flex; justify-content: center; align-items: center; } #chart { width: 90%; max-width: 1200px; } </style> <!-- Your markup must be inside the template --> <section flex flex-full-center> <div id="chart"></div> </section> </template> <!-- Your script goes here --> </dom-module>
3. Alternative: Access via Shadow Root
If you ever need more control, you can directly query the component's Shadow DOM:
const chartElement = this.shadowRoot.getElementById("chart");
This works the same way as document.getElementById, but targets the isolated Shadow DOM tree of your component.
Key Takeaway
Never use document.getElementById to access elements inside a Polymer component—always use this.$.[elementId] or this.shadowRoot from within the component's lifecycle methods. This respects Shadow DOM encapsulation and ensures your elements are available when your component is ready.
内容的提问来源于stack exchange,提问作者Dorian Seguin

