javascript - 如何为用 svelte.js 编写的应用程序创建插件?

标签 javascript plugins svelte svelte-3

如果我用纯 JS 编写应用程序,我会像这样建立插件连接:

App.js

var App = function(){ /* ... */ };
//...
App.prototype.regPlugin= function ( atr1, atr2, ... ) { /* ... */ };
//...
App.prototype.sendToEventBus = function ( atr1, ... ) { /* ... */ };
//...
var app = new App();
//...
var appModules = {};
//...
document.onreadystatechange = function () {
   if ( document.readyState === 'complete' ){
      for ( var module in AppModules ) {
        if ( AppModules[ module ] ) {
        try {
            AppModules[ module ].init( app );
        } catch(er) {
            //...
        }
      }
   }
}
//...

plugin.js

var MyPlugin = function (){ /*...*/ };
//...
MyPlugin.prototype.init = function ( app ) {
    this.app = app;
    //...
    app.regPlugin( plugAtr0 );
    //...
};
//...
MyPlugin.prototype.handleAny = function(){
   this.app.sendToEventBus( /* my event */ );
};
//...
appModules.myPlugin = new MyPlugin();

如何在 svelte.js 上为应用程序制作类似的插件?
自定义元素不太适合于此。

最佳答案

好吧,如果您愿意的话,您可以做一些非常类似的事情。 Svelte 只为您提供一个 UI 组件,您可以在页面上的任何位置呈现。它不会接管你的整个 JS。

有一件事是,您的 Svelte 应用程序很可能会使用 ES import 进行捆绑(Rollup 或 Webpack)。陈述。这意味着您的代码将驻留在 ES 模块中,并且局部变量不会自动附加到 window ES 模块中的对象。所以你必须明确这一点。所以你的代码会变成这样:

App.js (presumably your application entry point)

import App from './App.svelte'

const app = new App({
  target: document.body,
  props: {
    name: 'world',
  },
})

const appModules = {}

// expose appModules as a global variable
window.appModules = appModules

document.onreadystatechange = function() {
  if (document.readyState === 'complete') {
    debugger
    for (var module in appModules) {
      if (appModules[module]) {
        try {
          appModules[module].init(app)
        } catch (er) {
          //...
        }
      }
    }
  }
}

现在,app是您的根 Svelte 组件。它将生活在 App.svelte 中文件。 Svelte 允许您通过exporting const or function 向组件添加实例方法.

App.svelte

您可以导出constfunction在 Svelte 组件上拥有实例方法。

<script>

  export function regPlugin(...) { ... }

  // or
  export const sentToEventBus(...) { ... }

</script>
...

然后...瞧?您的代码中还有其他内容吗?

上述代码的一个问题可能是 App组件将在您的插件有机会注册之前呈现。

您可以使用 App 中的 prop 来修复此问题成分。为了能够从“ Controller 代码”更改此 Prop 的值,您可以使用 $set 组件的方法。您还可以设置accessors您的组件上的选项。您可以使用 bundler 插件选项全局执行此操作,也可以使用 <svelte:options> 在各个组件上启用它。 .

如果您需要一些仅在应用程序准备就绪后运行的自定义逻辑,您可以在 "reactive statement" 中执行此操作.

App.svelte

<svelte:options accessors={true} />

<script>
  export function regPlugin() {}
  export function sentToEventBus() {}

  export let ready = false

  $: if (ready) {
    // code to run when ready
  }
</script>

{#if ready}
  <!-- content to show when ready (all plugins initialized) -->
  <!-- most likely, you'd put other Svelte components in there -->
{:else}
  <div>Loading...</div>
{/if}

当应用程序准备好启动时,您可以切换此 Prop :

App.js

document.onreadystatechange = function() {
  if (document.readyState === 'complete') {
    for (var module in appModules) {
      ...
    }

    app.$set({ ready: true })
    // or
    app.ready = true
  }
}

或者,您可能更愿意将插件初始化代码移至应用程序组件中。由于这里有一个“静态”状态,在 appModules 中变量,您必须将其放入静态 <script context="module"> 中您组件的一部分:

App.svelte

<script context="module">
  // this block only runs once, when the module is loaded (same as 
  // if it was code in the root of a .js file)

  // this variable will be visible in all App instances
  const appModules = {}

  // make the appModules variable visible to the plugins
  window.appModules = appModules

  // you can also have static function here
  export function registerPlugin(name, plugin) {
    appModules[name] = plugin
  }
</script>

<script>
  // in contrast, this block will be run for each new instance of App

  ...

  let ready

  document.onreadystatechange = function() {
    if (document.readyState === 'complete') {
      // NOTE appModules bellow is the same as the one above
      for (var module in appModules) {
        // ...
      }
      ready = true
    }
  }
</script>

{#if ready}
  ...
{/if}

静态函数addPlugin可以从其他模块作为命名导出进行访问:

import { addPlugin } from './App.svelte'

这可能更适合捆绑应用程序/带有模块的应用程序的上下文,而不是将内容附加到 window (因此在全局命名空间中遇到冲突的风险)。取决于你在做什么...

关于javascript - 如何为用 svelte.js 编写的应用程序创建插件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59266902/

相关文章:

javascript - 计算字典中的项目数

javascript - 如何根据 HTML 中包含的特定脚本排除 Google 跟踪代码管理器中的标记

java - 正在创建文件,但 FileConfiguration 未在其中放入文本

jquery - 如何在窗口大小调整时实现平滑的字体大小变化?

Svelte 响应式语句,仅在某些引用变量发生更改时更新

当任何一组变量发生变化时,Svelte 执行函数

javascript - 使用 `.toggle()` 而不是应用类来显示内容

javascript - cropper.js 有问题

plugins - 尝试在Moodle上安装插件后出现错误500

django - 如何将 Django 与 Svelte 结合使用?