Exi*_*orp 2 javascript d3.js rollupjs svelte
我一直在尝试将最基本的D3示例放到Svelte应用程序中,但无法使其正常工作。起初,我尝试安装D3为节点模块:npm install d3
但这产生相同的结果(缺乏结果)作为进口D3作为从CDN内外部脚本index.html
:<script src="https://d3js.org/d3.v5.min.js"></script>
。无论使用哪种方法,我都会在应用启动时收到一堆循环依赖警告:
(!) Circular dependency: node_modules\d3-selection\src\selection\index.js -> node_modules\d3-selection\src\selection\select.js -> node_modules\d3-selection\src\selection\index.js
Run Code Online (Sandbox Code Playgroud)
但是该应用程序启动时没有任何错误,也没有发生D3动态格式化,也没有任何错误在Chrome内的DevTools控制台中弹出。
Svelte组件如下所示:
<script>
import * as d3 from 'd3';
var data = [30, 86, 168, 281, 303, 365];
d3.select(".chart")
.selectAll("div")
.data(data)
.enter()
.append("div")
.style("width", function(d) {
return d + "px";
})
.text(function(d) {
return d;
});
</script>
<style>
.chart div {
font: 10px sans-serif;
background-color: steelblue;
text-align: right;
padding: 3px;
margin: 1px;
color: white;
}
</style>
<div class="chart"></div>
Run Code Online (Sandbox Code Playgroud)
如预期的那样,将上面的代码放入静态HTML文件中会生成条形图。但是当作为Svelte组件运行时,不会显示任何内容。
我的rollup.config.js是:
import svelte from 'rollup-plugin-svelte';
import resolve from 'rollup-plugin-node-resolve';
import commonjs from 'rollup-plugin-commonjs';
import livereload from 'rollup-plugin-livereload';
import { terser } from 'rollup-plugin-terser';
const production = !process.env.ROLLUP_WATCH;
export default {
input: 'src/main.js',
output: {
sourcemap: true,
format: 'iife',
name: 'app',
file: 'public/bundle.js',
globals: { 'd3': 'd3' },
external: [ 'd3' ]
},
plugins: [
svelte({
dev: !production,
css: css => { css.write('public/bundle.css'); }
}),
resolve({ browser: true }),
commonjs(),
!production && livereload('public'),
production && terser()
],
watch: {
clearScreen: false
}
};
Run Code Online (Sandbox Code Playgroud)
...和index.html是:
(!) Circular dependency: node_modules\d3-selection\src\selection\index.js -> node_modules\d3-selection\src\selection\select.js -> node_modules\d3-selection\src\selection\index.js
Run Code Online (Sandbox Code Playgroud)
我怀疑Rollup不能正确地捆绑D3模块,但是作为一个外部脚本<body>
,理论上应该可以,但事实并非如此。请为我指出正确的方向,我花了太多时间尝试使其正常工作,而作为JS noob则没有选择的余地。谢谢!
第<div class="chart"></div>
一次运行代码时该元素不存在- <script>
实例化该组件时run 的内容。如果您需要访问组件内部的DOM元素,它将首先在onMount内部可用:
<script>
import { onMount } from 'svelte';
// other code...
onMount(() => {
d3.select('.chart')
// ...
});
</script>
Run Code Online (Sandbox Code Playgroud)
.chart
但是,使用like这样的选择器很危险,因为如果在D3页上有多个组件,则会选择错误的内容。最好使用bind:this代替:
<script>
import { onMount } from 'svelte';
// other code...
let el;
onMount(() => {
d3.select(el) // no danger of selecting the wrong element
// ...
});
</script>
<div class="chart" bind:this={el}></div>
Run Code Online (Sandbox Code Playgroud)
现在,您需要更改的只是CSS —因为Svelte会丢弃它认为未使用的选择器,并且由于它不知道D3将要做什么,因此它将删除.chart div {...}
。而是使用:global(...)修饰符将顶级元素内的div定位为目标:
<style>
.chart :global(div) {
/* styles */
}
</style>
Run Code Online (Sandbox Code Playgroud)
通过这些更改,它可以完美运行:
https://svelte.dev/repl/8722c32f4e1a44a98e3a3fc8a095b2d7?version=3.5.3
但是在这种情况下,D3并没有真正为聚会带来任何好处。您可以更简单地达到相同的结果:
<script>
var data = [30, 86, 168, 281, 303, 365];
</script>
<style>
.chart div {
font: 10px sans-serif;
background-color: steelblue;
text-align: right;
padding: 3px;
margin: 1px;
color: white;
}
</style>
<div class="chart">
{#each data as d}
<div style="width: {d}px">
{d}
</div>
{/each}
</div>
Run Code Online (Sandbox Code Playgroud)
现在,您的应用程序包含的JavaScript数量大大减少,而且您可以编写的代码更少了。演示在这里:https : //svelte.dev/repl/be5cac1695554b8e9ee6d0bc14b9dff1?version=3.5.3
归档时间: |
|
查看次数: |
842 次 |
最近记录: |