フロントエンドの上級者向けコースでは、JavaScript のストレージ機能の使い方を学習します。

フロントエンドの上級者向けコースでは、JavaScript のストレージ機能の使い方を学習します。

序文

どの SaaS 企業も、独自のローコード プラットフォームを持つ必要があります。ビジュアル ローコード フロントエンド開発のプロセスでは、多くの興味深い技術要件が見つかります。これらの要件を解決するプロセスでは、多くの場合、多くの利益が得られます。今日は、Dooring - javascript 関数ストレージの開発プロセスで遭遇したフロントエンドの技術的問題を共有しましょう。

背景

フロントエンド ページを構築するには、次の 3 つの要素が必要であることは誰もが知っています。

  • 要素 (UI)
  • データ
  • イベント/インタラクション

データドリブンビューの時代では、これら 3 つの要素の関係は、多くの場合、次のようになります。

ビジュアル構築プラットフォームの設計アイデアは、多くの場合、上記のプロセスに基づいています。ユーザーがビューを作成して対話するためのエディター環境を提供する必要があります。ユーザーが保存する最終製品は、次のようになります。

{
    "name": "ドアリングフォーム",
    "背景色": "#666",
    "share_url": "http://xxx.cn",
    "マウントイベント": [
        {
            "id": "123",
            "関数": () => {
                // 初期化ロジック GamepadHapticActuator();
            },
            "ソースデータ": []
        }
    ]、
    "体": [
        {
            "名前": "ヘッダー",
            "イベント": [
                {
                    "id": "123",
                    「タイプ」:「クリック」、
                    "関数": () => {
                        // コンポーネントのカスタムインタラクションロジック showModal();
                    }
                }
            ]
        }
    ]
}

質問は、JSON 文字列 (JSON.stringify シリアル化を通じて) を保存できるが、関数を一緒に保存するにはどうすればよいかということです。関数を保存した後、ページがレンダリングされるときに js がこの関数を正常に実行するようにするにはどうすればよいでしょうか。

実施計画の考え方

js オブジェクトを json に変換するには JSON.stringify を使用できることをご存じでしょうが、次のような制限もあります。

  1. 値に toJSON() メソッドがある場合、toJson() はどの値がシリアル化されるかを定義します。
  2. 配列以外のオブジェクトのプロパティは、シリアル化された文字列内で特定の順序で表示されるとは限りません。
  3. ブール値、数値、文字列のラップされたオブジェクトは、シリアル化時に自動的に対応する元の値に変換されます。
  4. 未定義、任意の関数、およびシンボルの値は、シリアル化中に無視されるか (配列以外のオブジェクトのプロパティ値に表示される場合)、null に変換されます (配列に表示される場合)。関数とundefinedを別々に変換すると、JSON.stringify(function(){})やJSON.stringify(undefined)のようにundefinedが返されます。
  5. キーとしてシンボルを持つすべてのプロパティは、replacer パラメータで必須であっても完全に無視されます。
  6. Date は toJSON() を呼び出して文字列に変換します (Date.toISOString() と同じ)。そのため、文字列として扱われます。
  7. NaN および Infinity 形式の値および null は null として扱われます。
  8. Map/Set/WeakMap/WeakSetを含む他のタイプのオブジェクトは、列挙可能なプロパティのみをシリアル化します。

項目 4 を見ると、シリアル化するオブジェクトに関数が含まれている場合、その関数は無視されることがわかります。したがって、JSON.stringify を使用して関数を保存できないのは常識ですが、他に方法はあるのでしょうか。

まず関数を文字列に変換し、次に JSON.stringify でシリアル化してバックエンドに保存し、最後にコンポーネントが使用されるときに eval または Function を使用して文字列を関数に変換することが考えられます。一般的なプロセスは次のとおりです。

はい、理想は美しいですが、現実は_______です。

次に、キーリンク func2string と string2func がどのように実装されているかを分析しましょう。

js ストレージ機能ソリューション設計

JSON API に詳しい方は、JSON.stringify が 3 つのパラメータをサポートし、2 番目のパラメータ replacer が関数または配列になる可能性があることをご存知かもしれません。関数としては、キーと値という 2 つのパラメーターがあり、どちらもシリアル化されています。 関数は、以下に示すように、JSON 文字列で値を返す必要があります。

  • 数値が返された場合は、対応する文字列に変換され、属性値として JSON 文字列に追加されます。
  • 文字列が返された場合、その文字列はプロパティ値としてJSON文字列に追加されます。
  • ブール値が返される場合、プロパティ値として「true」または「false」が JSON 文字列に追加されます。
  • その他のオブジェクトが返される場合、そのオブジェクトは各プロパティの replacer メソッドを呼び出して、JSON 文字列に再帰的にシリアル化されます。オブジェクトが関数である場合を除き、その場合には JSON 文字列にシリアル化されません。
  • undefined が返された場合、プロパティ値は JSON 文字列に出力されません。

したがって、値の型が関数であるデータを 2 番目の関数パラメータに変換できます。次のように:

定数文字列化 = (obj) => {
    JSON.stringify(obj, (k, v) => { を返す
      if(typeof v === '関数') {
          `${v}` を返す
      }
      リターンv
    })
}

この方法では、関数をバックエンドに保存できるようです。次に、関数文字列を使用して json を逆シリアル化する方法を見てみましょう。

関数を文字列に変換したので、逆解析するときにどの文字列を関数に変換する必要があるかを知る必要があります。関数に対して何もしない場合は、手動で識別する必要がある場合があります。

人肉認識の欠点は、関数特性を持つ文字列を抽出するために正規表現を使用する必要があることですが、関数の書き方は多種多様であり、多くの状況を考慮する必要があります。関数特性を持つ文字列が必ず関数であるという保証はありません。

そこで、複雑な正規表現を書かずに関数を抽出するより簡単な方法に変更しました。この方法では、関数がシリアル化されるときに識別子を挿入して、次のように、どの文字列を関数として解析する必要があるかを知ることができます。

文字列化: 関数(obj: any, space: number | string, error: (err: Error | unknown) => {}) {
        試す {
            JSON.stringify(obj, (k, v) => { を返す
                if(typeof v === '関数') {
                    `${this.FUNC_PREFIX}${v}` を返します
                }
                リターンv
            }、 空間)
        } キャッチ(エラー) {
            エラー && エラー(err)
        }
}

this.FUNC_PREFIX は、JSON.parse を使用するときに関数をすばやく解析できるように定義した識別子です。JSON.parse は、JSON.stringify の 2 番目のパラメータに似た 2 番目のパラメータもサポートしています。次のように変換できます。

解析: 関数(jsonStr: 文字列、エラー: (err: エラー | 不明) => {}) {
        試す {
            JSON.parse(jsonStr, (キー, 値) を返します => {
                if(値 && 値のタイプ === '文字列') {
                    戻り値.indexOf(this.FUNC_PREFIX) > -1 ? 新しい Function(`return ${value.replace(this.FUNC_PREFIX, '')}`)() : 値
                }
                戻り値
            })
        } キャッチ(エラー) {
            エラー && エラー(err)
        }
    }

新しい関数は文字列を js 関数に変換できます。文字列パラメータのみを受け入れます。オプションのパラメータはメソッドの入力パラメータであり、必須のパラメータはメソッド本体の内容です。わかりやすい例:

上記コードの関数本体の内容は次のとおりです。

新しい関数(`return ${value.replace(this.FUNC_PREFIX, '')}`)()

return を使う理由は、元の関数をそのまま戻すためです。eval も使えますが、世論としては慎重に使った方が良いでしょう。

上記のソリューションでは、フロントエンドストレージ機能はすでに実現されていますが、よりエンジニアリング性と堅牢性を高めるには、より多くのユーザーがすぐにライブラリを使用できるように、多くの追加処理と最適化が必要です。

やっと

より多くの人がこの関数を直接使用できるようにするために、完全な JSON シリアル化ソリューションをクラス ライブラリにカプセル化しました。

サポート機能は次のとおりです。

  • stringify はネイティブ JSON に基づくシリアル化関数とエラーコールバックをサポートします。stringify
  • parseはネイティブJSON.parseに基づくデシリアライズ関数とエラーコールバックをサポートします。
  • funcParse は、js オブジェクト内の関数をワンクリックでシリアル化し、js オブジェクトの型を変更せずに維持します。

インストール方法は以下の通りです。

# または npm install xijs
糸を追加 xijs

使用:

'xijs' から { parser } をインポートします。

定数a = {
    x: 12,
    b: 関数() {
      警告(1)
    }
 }
 
 定数 json = parser.stringify(a);
 定数 obj = parser.parse(json);
 //メソッドobj.b()を呼び出します。

要約する

これで、JavaScript を使用して関数を保存する方法に関するこの記事は終了です。JavaScript を使用して関数を保存する方法に関するより関連性の高いコンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM を応援していただければ幸いです。

以下もご興味があるかもしれません:
  • JS 配列の高度な例 [いくつかの配列関数の使用法]
  • 高度な JS 関数継承の使用例の分析
  • 高度な JS 関数プロトタイプの使用例の分析
  • JavaScript の分割関数と結合関数の高度な使用方法のヒント
  • JavaScript 関数の高度な説明

<<:  CSSのclip-pathプロパティを使用して不規則なグラフィックを表示する

>>:  テキストエリアタグはサイズ変更できず、マウスでドラッグすることもできません

推薦する

WeChatミニプログラムで検索キーワードを強調表示するサンプルコード

1. はじめにプロジェクトで要件に遭遇したら、データを検索してキーワードを強調表示します。要件を受け...

Windows 環境での MYSQL5.7 設定ファイルの場所のグラフィカル分析

1. MYSQLインストールディレクトリ次のようにコードをコピーします。 select @@bas...

Alibaba Cloud Server で MySQL デュアルマシン ホットスタンバイを手動で実装する 2 つの方法

1. コンセプト1. ホットバックアップとバックアップの違いホット バックアップは高可用性 (HA)...

MySQL は正常に起動するがポートをリッスンしない場合の解決策

問題の説明MySQL が正常に起動しました。以下に示すように、 ps -ef |grep mysql...

MYSQLパターンマッチングREGEXPの使用に関する一般的な話など

のようにLIKE ではデータ全体が一致する必要がありますが、REGEXP では部分的な一致のみが必要...

MySQLのSQL文はインデックスを使用しません

インデックス集約を使用しない MySQL クエリご存知のとおり、インデックスを追加することはクエリ速...

Mybatis ファジークエリ実装方法

Mybatis ファジークエリ実装方法mybatis のリバース アシスタントは非常に使いやすく、通...

Node.js管理ツールnvmの詳細なインストール手順

いいえnvmはnodejsの複数のバージョンを管理する役割を担っています。インストール: https...

Rx レスポンシブプログラミングについての簡単な説明

目次1. 観察可能2. 高階関数3. エクスプレスボックスモデル3.1. エクスプレスボックスモデル...

HTML5+CSS3 ヘッダー作成例と更新

前回、私たちは 2 つのヘッダー レイアウト (フレックスボックス 1 つとフロート 1 つ) を考...

Nginx の http リソース リクエスト制限の詳細な説明 (3 つの方法)

前提条件: nginx には、ngx_http_limit_conn_module モジュールと n...

Django+mysql の設定と簡単な操作データベースのサンプルコード

ステップ1: MySQLドライバをダウンロードするcmdは作成されたDjangoプロジェクトディレク...

IMG での UserMap の使用例

usemap は <img> タグの属性であり、使用するイメージ マップの名前を指定する...

Linux ホスト上で複数の MySQL データベースを起動する方法

今日は、Linux ホスト上で 4 つの MySQL データベースを起動する方法について説明します。...

jQuery は呼吸カルーセルを実装します

この記事では、ブレッシングカルーセルを実装するためのjQueryの具体的なコードを参考までに共有しま...