我可以将 JS 代码从 Svelte 组件文件移到其他文件 js 文件吗?

Can I move JS code out of Svelte component file to other file js file?

我目前正在 Bucklescript/ReasonML 探索 Svelte 3 的下一个项目。典型的 Svelte 组件是 .svelte 文件:

<script>
  let name = 'world';
</script>

<h1>Hello world!</h1>

相反,我可以使用带有 srcscript 标签或等效标签来将 JS 代码保存在单独的文件中吗?

<script src='./some-file.js'></script>

通过将 js 代码移动到一个单独的文件,Bucklescript 编译器的目标(它是一个 JS 文件)可以用于该组件。

Vue.js 已经通过他们的 SFC .vue 文件支持这一点。

On a side note: I could use Vue.js for this but the presence Virtual DOM is problematic for legacy codebase. And, Svelte is diminishing at runtime and thus very much desirable. Also, the use this in Vue makes things awkward in Ocaml/Reason.

据我所知,目前还不可能。

你可以做的是从 js 文件中导出你需要的所有内容,然后在组件中导入它们:https://svelte.dev/repl/1d630ff27a0c48d38e4762cf6b0c2da5?version=3.7.1

<script>
 import { name } from './mycode.js'
</script>

<h1>Hello {name}!</h1>
export let name = 'World';

然而,这只是部分解决方案,因为文件中发生的任何数据突变都不会触发 DOM 的重新渲染,因为 Svelte 不会编译 .js 文件,也不会能够添加自己的代码使值无效:https://svelte.dev/repl/c4b41b769ed747acb01a02a9af33e545?version=3.7.1

<script>
 import { name, handleClick } from './mycode.js'
</script>

<h1 on:click={handleClick}>Hello {name}!</h1>
export let name = 'World';
export const handleClick = () => {
    name = 'Everyone';
}

但这并不意味着如果你愿意付出额外的努力来实现这一目标,你就不会狡猾:https://svelte.dev/repl/8e259df629614ac99cb14cfae2f30658?version=3.7.1

<script>
 import { name, handleClick } from './mycode.js'

 const onClick = () => {
     handleClick();
     name = name;
 }
</script>

<h1 on:click={onClick}>Hello {name}!</h1>
export let name = 'World';
export const handleClick = () => {
    name = 'Everyone';
}

额外的行 name = name 强制 DOM 更新。

这可以通过 svelte.preprocess API 实现,您最常通过 rollup-plugin-svelte 或 svelte-loader 中的 preprocess 选项来实现。像这样的东西应该可以工作(虽然我还没有测试过):

const path = require( 'path' )
const fs = require( 'fs' )
...

plugins: [
  svelte({
    // ...
    preprocess: {
      script: ({ content, attributes, filename }) => {
        if ( 'string' === typeof attributes.src ) {
          const file = path.resolve(path.dirname(filename), attributes.src);
          const code = fs.readFileSync(file, 'utf-8');
          return {code, dependencies: [file]};
        }
      }
    }
  })
]