絵本のコールバックをレンダリングする

11614 ワード

ストーリーブック.JSは素晴らしいアウトフラットです.あなたがRizzoに精通しているならば、あなたはどのくらいの人々が生活スタイルガイド問題を解決しようとしているかについてわかっています.問題は決して“我々はできませんでしたか?”それは“すべてのこのコスト削減効果は?”です.StoryBookとはもはや疑問であり、それはUI開発の将来を表しています.
しかし、ほとんどの新しいもののように、我々のプロジェクトの膨大な数は、彼らが十分に近代的である前に、赤いテープの海を通過する必要があります.つまり、私たちの多くはまだそれらを生成するのではなく、DOM要素を飾っています.そして、それはStorybookであるコンポーネントの良さを活用することを難しくします.

問題
ストーリーブックは、HTMLコンポーネントの開発をサポートしていますが、現在は、新たにレンダリングされたDOM要素への参照を持つストーリーにコールバックを提供しません.また、そのコールバック内のストーリーのメタへのアクセスが必要です.JavaScriptを必要とする場合は、フレームワークを使用して、おそらくアドオンAPIはおそらく、彼らがDEVに制御を渡す起動する場合は分解を開始すると思います.

ゴール
我々が必要とするものは、それがレンダリングされたならば、我々のDOM要素と物語のメタへのリファレンスでコールバックを得ることができることです.これは特に、要素が存在するまでスクリプトを実行できないjQueryの開発者によって必要とされます.

回避策
これは、それがサポートされている童話機能を活用しているが、使用方法が非標準的であり、いつかネイティブになる可能性があるため解決されていないため、これはハックではありません.これは、信用がコミュニティに行くようにDiscordメッセージ、github問題とソースコードで見つけたもののコレクションです.

救助にデコレーター.
StoryBookのデコレータ機能は、ストーリーブック内だけでカスタムの変更を許可し、我々のテストスイートはまだ純粋なコンポーネントを取得します.デコレータは、Addon APIを使用してレンダリングイベントを聞くことができますが、まだ我々の話と通信することができます.
これにより、コールバックを作成できます.私はグローバルにこれを解決するために選択していますが、どこでもデコレーターを行います.
目的は、見つけるためにセレクタを使用してデコレータを供給し、それが見つけたものを呼び出す関数です.
注意:私は公式アドオンに必要なアドオン登録をスキップしています.
// .storybook/callback-addon/decorators.js
import addons from "@storybook/addons";

export const withRenderCallback = (selector, callback) => {
  return (Story, context) => {
    // your needs from context may vary
    const { args, id, kind, name, ...rest } = context;
    addons.getChannel().once(STORY_RENDERED, (e) => {
      callback(document.querySelector(selector), { args, id, kind, name });
    });
    return Story();
  };
};
今、私たちのストーリーファイル内から我々は必要に応じて飾ることができます
// stories/Button.stories.js
import { withRenderCallback } from "./.storybook/callback-addon/decorators.js";
import { Button } from "/button.ts";

export default {
  title: "Example/Button",
  argTypes: {
    onclick: { action: "button clicked" }
  }
}

// create a js component that renders our HTML
const Component = args => {
  return `<a data-story-of="Button" class="btn btn-primary">This is a button</a>`;
}

// create a template for bindings
const Template = (args) => Component(args);

// bind and decorate a story
export const Primary = Template.bind({});
Primary.decorators = [
  withRenderCallback(`[data-story-of="Button"]`, (element, props) => {
      const { onclick } = props.args;
      element.onclick = onclick;
      const btn = new Button($(element));
    }),
];

ノブを動かす
あなたがこれを得たならば、それは多分あなたが現在あなたの構成要素をコントロールしたいからでしょう.プロシージャの更新プロップを制御しますが、コンポーネントのメソッドを呼び出しません.ノブはこれを行うことができますが、手動で.
import { button } from "@storybook/addon-knobs";
...
export const Primary = Template.bind({});
Primary.decorators = [
  withRenderCallback(`[data-story-of="Button"]`, (element, props) => {
      const { onclick } = props.args;
      element.onclick = onclick;
      const btn = new Button($(element));
      button(
        "set 'loading'",
        () => {
          btn.setState("loading");
          return false; // prevent further processing
        },
        "group_1"
      );
      button(
        "set 'default'",
        () => {
          btn.setState("default");
          return false;
        },
        "group_1"
      );
    }),
];
そして、それ!
これは非常に特定のデモだったので念頭に置いてデコレータ複数のレベルで動作することができます.共通のコントロールは、例えば、ストーリーレベルで設定することができます.このメソッドは、多くの状況で動作することがありますが、私は常に最初に正式にサポートされているパターンを求めることをお勧めします.