序文vue3サンドボックスには主に2つの種類があります
ブラウザコンパイル版レンダリング関数のコンパイル結果 <div>{{テスト}}</div> <div>{{Math.floor(1)}}</div> に Vue を継承します。 関数 render(_ctx, _cache, $props, $setup, $data, $options) を返します { (_ctx) で{ 定数{ 表示文字列: _表示文字列、 作成VNode: _createVNode、 フラグメント: _Fragment、 オープンブロック: _openBlock, ブロックの作成: _createBlock、 } = _Vue; 戻る ( _openBlock(), _createブロック( _断片、 ヌル、 [ _createVNode("div", null, _toDisplayString(test), 1 /* テキスト */), _createVNode( "div", ヌル、 _toDisplayString(Math.floor(1))、 1 /* テキスト */ )、 ]、 64 /* 安定フラグメント */ ) ); } }; 上記のコードから、変数識別子にプレフィックスが追加されておらず、スコープ チェーンを拡張するために with 構文でラップされているだけであることがわかります。では、js サンドボックス インターセプションはどのように実現されるのでしょうか。たとえば、変数 test です。理論的には、現在のスコープ チェーンには test 変数はありません。変数は、グローバル スコープが見つかるまで、前のスコープから検索されます。ただし、実際には、_ctx でのみ検索されます。原理は非常に単純です。_ctx はプロキシ オブジェクトです。では、Proxy を使用してインターセプトするにはどうすればよいでしょうか。サンプル コードは次のとおりです。 定数 GLOBALS_WHITE_LISTED = 「無限大、未定義、NaN、isFinite、isNaN、parseFloat、parseInt、decodeURI」+ 「decodeURIComponent、encodeURI、encodeURIComponent、Math、Number、Date、Array」+ "オブジェクト、ブール値、文字列、正規表現、マップ、セット、JSON、Intl、BigInt"; const isGloballyWhitelisted = (キー) => { GLOBALS_WHITE_LISTED.split(",").includes(key); を返します。 }; const hasOwn = (obj, キー) => { Object.prototype.hasOwnProperty.call(obj, key) を返します。 }; 定数 origin = {}; const _ctx = 新しいプロキシ(origin, { get(ターゲット、キー、受信者) { if (hasOwn(ターゲット、キー)) { Reflect.get(ターゲット、キー、レシーバー); } それ以外 { コンソール.警告( `レンダリング中にプロパティ ${JSON.stringify(key)} がアクセスされました ` + `ただし、インスタンスでは定義されていません。` ); } }, has(ターゲット, キー) { // グローバル オブジェクトの場合は false を返し、get インターセプションをトリガーせず、前のスコープから変数を検索します。// グローバル オブジェクトでない場合は true を返し、get インターセプションをトリガーします。 return !isGloballyWhitelisted(key); }, }); コードは非常にシンプルですが、なぜこのようなシンプルなコードで傍受が実現できるのでしょうか? with ステートメントは has インターセプションをトリガーするため、has が true を返すと、プロキシ オブジェクトの get インターセプションがトリガーされます。false を返すと、プロキシ オブジェクトの get インターセプションはトリガーされず、変数は現在のプロキシ オブジェクトで検索されず、上位スコープで直接検索されます。 ローカルプリコンパイルバージョン<div>{{テスト}}</div> <div>{{Math.floor(1)}}</div> に 輸入 { toDisplayString を _toDisplayString として、 createVNode を _createVNode として、 フラグメントとしての_Fragment、 openBlock を _openBlock として、 createBlock を _createBlock として、 } から "vue" へ; エクスポート関数 render(_ctx, _cache, $props, $setup, $data, $options) { 戻る ( _openBlock(), _createブロック( _断片、 ヌル、 [ _createVNode("div", null, _toDisplayString(_ctx.a), 1 /* テキスト */), _createVNode( "div", ヌル、 _toDisplayString(Math.floor(1))、 1 /* テキスト */ )、 ]、 64 /* 安定フラグメント */ ) ); } 上記のコードから、ホワイトリストに含まれない識別子には _ctx 変数がプレフィックスとして付けられていることがわかります。では、これはどのように行われるのでしょうか?テンプレートをローカルでコンパイルすると、変換フェーズ中に変数式ノード NodeTypes.SIMPLE_EXPRESSION がプレフィックスとして付加されます。サンプル コードは次のとおりです。 定数 GLOBALS_WHITE_LISTED = 「無限大、未定義、NaN、isFinite、isNaN、parseFloat、parseInt、decodeURI」+ 「decodeURIComponent、encodeURI、encodeURIComponent、Math、Number、Date、Array」+ "オブジェクト、ブール値、文字列、正規表現、マップ、セット、JSON、Intl、BigInt"; const isGloballyWhitelisted = (キー) => { GLOBALS_WHITE_LISTED.split(",").includes(key); を返します。 }; const isLiteralWhitelisted = (キー)=>{ 'true,false,null,this'.split(',').includes(key) を返します。 } エクスポート関数 processExpression( ノード ){ const rewriteIdentifier = (raw) => { `_ctx.${raw}` を返す } 定数rawExp = ノード.content if (isSimpleIdentifier(rawExp)) { const isAllowedGlobal = isGloballyWhitelisted(rawExp) 定数 isLiteral = isLiteralWhitelisted(rawExp) if (!isAllowedGlobal && !isLiteral) { ノードのコンテンツ = rewriteIdentifier(rawExp) } 戻りノード } もちろん、上記のコードは簡略化されたバージョンにすぎません。元のプラグインでは、__props $setup を正確にしたり、変数クエリパスを短縮したり、パフォーマンスを向上させたり、矢印関数などの複雑な式を babel 経由でコンパイルしたりもしています。 要約するvue3 js サンドボックスのメカニズム全体が説明されています。ブラウザーでコンパイルされたバージョンは、ステートメント変数クエリでインターセプトできることを知らなかったため、長い間私を悩ませていました。 以上がvue3のサンドボックスの仕組みの詳しい説明です。vue3のサンドボックスの仕組みについてさらに詳しく知りたい方は、123WORDPRESS.COM内の他の関連記事もぜひご覧ください! 以下もご興味があるかもしれません:
|
>>: MySQL で浮動小数点データを文字データに変換するときに起こりうる問題の詳細な説明
目次1. LVS 負荷分散2. 負荷分散LVSの基本紹介3. LVSアーキテクチャ3.1 ロードバラ...
ローカル環境はWindows10+WSL2(Ubuntu)です。サーバーにDockerをインストール...
<br />関連記事: ハイパーリンクを表示して開く方法症状<br />ユー...
/usr/local/nginx/conf と入力する sudo cd /usr/local/ngi...
insとdel は、HTML 4.0 で導入され、文書の作成時に作成者が共同作業できるようにし、また...
GTIDベースのレプリケーション導入GTID ベースのレプリケーションは、MySQL 5.6 以降に...
前回の記事「202 個の無料高品質 XHTML テンプレート (1)」に続き、123WORDPRES...
目次問題の説明Vueの動的コンポーネントとはアプリケーションシナリオの説明実装手順ステップ 1 (新...
この記事では、Dockerを使用してMySQLデータベースとリモートアクセス構成をデプロイする方法を...
目次複数テーブル結合クエリ内部結合左結合右結合サブクエリ要約する複数テーブル結合クエリテーブル間の接...
背景: 最近、資産報告関連の機能に取り組んでおり、中国語入力をサポートする必要があります。通常のショ...
CN2ラインとは何ですか? CN2 は、China Telecom Next Carrier Ne...
この記事の例では、アップロード画像コントロールを実装するためのjsの具体的なコードを参考までに共有し...
ワームは、その名前が示すように、自ら複製し、その数は倍増、つまり指数関数的に増加します。 MySQL...
1. 時間差関数(TIMESTAMPDIFF、DATEDIFF) MySQLを使用して時間差を計算...