繁体   English   中英

将 HTML 元素添加到 vue 模板

[英]Adding HTML element to a vue template

我正在使用一个图表组件 (Chartist),它在渲染 SVG 时需要一个 HTML 元素作为父元素。

图表可以使用的元素是在v-for循环期间生成的,这意味着它们不会在图表呈现时添加到 DOM 中。

代码看起来像这样(在 vue 中):

<div v-for="chart in charts">
  <h1>{{chart.Title}}</h1>
  <div class="ct-chart" :id="'chart-' + chart.name"></div>
  {{generateChart('#chart-' + chart.name, chart.Data}}
  <div>
    <span v-for="l in legend" :class="chart.ClassName">{{l.DisplayName}}</span>
</div>

在组件中:

generateChart(chartName: string, data: IChartData) {
    /* More code here */

    //doesn't get added (can't find html node in dom)
    new Chartist.Line(chartName, data, options);

    // this worked
    //var element = document.createElement("DIV");
    //element.className = "ct-chart";
    //document.body.appendChild(element);
    //new Chartist.Line(element, data, options);

}

这导致 Chartist 在querySelectorAll上失败。

另一方面,如果我使用document.createElement生成一个元素并将其附加到 html 正文,则生成工作正常。

概括:

我想渲染一个需要 DOM 元素进行渲染的图表。 但是由于 Vue 在它的虚拟 DOM 中渲染所有东西,所以当 Vue 渲染视图(包括图表)时没有可用的元素。

问题:

如何告诉 vue 添加预先创建的 HTML 元素? 或者我怎样才能推迟图表生成,直到 vue 将所有内容添加到真实的 DOM 中?

解决方法:

我正在使用超时 ( setTimeout ) 来推迟图表渲染,以便 Vue 可以在我调用图表渲染函数之前完成。

首先,不要在这样的模板中使用函数 模板被转换为渲染函数,并且每当发生变化时都会执行该函数 - 在这种情况下,这意味着您将在每次渲染模板时创建新的图表对象......这是您不想要的。

你想要的是首先渲染 DOM 节点(没有任何图表),并在 DOM 准备好后使用挂载的钩子来初始化每个图表:

mounted: function () {
  this.$nextTick(function () {
    // Code that will run only after the
    // entire view has been rendered
  })
}

如果需要 DOM 元素引用,可以使用refs

另请注意,大多数动态创建 DOM 元素的库(如 Chartist)几乎总是需要一些清理代码以避免内存泄漏

或者只是使用一些 Vue 包装器,例如vue-chartist

据我了解,在 DOM 完全加载之前,您不想加载具有“.ct-chart”类的 div。

您可以做的是向您的 vue 组件添加一个v-if ,当 DOM 完全加载时,您可以调用您的generateChart()函数。

new Vue({
  el: '#app',
  data: {
   domloaded: false
  },
  created() {
     window.addEventListener('load', function () {
      domloaded = true;
   });
  }
}

然后你可以像这样添加一个 v-if 或者使用像mount()created()这样的生命周期钩子

<div v-for="chart in charts">
 <h1>{{chart.Title}}</h1>
 <div v-if="domloaded" class="ct-chart" :id="'chart-' + chart.name"></div>
  {{generateChart('#chart-' + chart.name, chart.Data)}}
 <div>
 <span v-for="l in legend" :class="chart.ClassName">{{l.DisplayName}}</span>
</div>

  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM