1. サンプルコード<!-- サブコンポーネント comA --> <テンプレート> <div class='デモ'> <スロット><スロット> <スロット名='テスト'></スロット> <スロット名='scopedSlots' テスト='デモ'></スロット> </div> </テンプレート> <!-- 親コンポーネント --> <comA> <span>これがデフォルトのスロットです</span> <template slot='test'>これは名前付きスロットです</template> <template slot='scopedSlots' slot-scope='scope'>これはスコープ付きスロットです (旧バージョン) {{scope.test}}</template> <template v-slot:scopedSlots='scopeProps' slot-scope='scope'>これはスコープ付きスロットです (新バージョン) {{scopeProps.test}}</template> </comA> 2. 現象を通して本質を見るスロットの役割は、コンテンツの配信を実現することです。コンテンツの配信を実現するには、次の 2 つの条件が必要です。
コンポーネント内で定義された
3. 実施原則
上記のプロセスから、次のことが推測できます。 1. 親コンポーネントテンプレートは子コンポーネントの前に解析されるため、親コンポーネントは最初にスロットテンプレートのコンテンツを取得します。 2. サブコンポーネントテンプレートは後で解析されるので、サブコンポーネントが 3. スコープスロットはサブコンポーネント内の変数を取得できるため、スコープスロットの スロット処理フェーズ全体は、おおまかに次の 3 つのステップに分かれています。
以下のコードを例に、スロットの動作プロセスを簡単に説明します。 <div id='アプリ'> <テスト> <テンプレートスロット="hello"> 123 </テンプレート> </テスト> </div> <スクリプト> 新しいVue({ el: '#app', コンポーネント: テスト: { テンプレート: '<h1>' + '<スロット名="hello"></スロット>' + '</h1>' } } }) </スクリプト> 4. 親コンポーネントのコンパイルフェーズコンパイルでは、テンプレート ファイルを { タグ: 'テスト', scopedSlots: { // スコープスロット // slotName: ASTNode, // ... } 子供たち: [ { タグ: 'テンプレート', // ... 親: parentASTNode、 children: [ childASTNode ], // スロットコンテンツの子ノード、つまりテキストノード 123 slotScope: undefined、// スコープ スロット バインディング値 slotTarget: "\"hello\"", // 名前付きスロット名 slotTargetDynamic: false // 動的にバインドされたスロットかどうか // ... } ] } 5. 親コンポーネントがレンダリングメソッドを生成する
(これ){ _c('div',{attrs:{"id":"app"}}, を返します。 [_c('テスト', [ _c('テンプレート',{スロット:"hello"},[_v("\n 123\n ")])],2) ]、 1) } 6. 親コンポーネントがVNodeを生成する
{ タグ: 'div', 親: 未定義、 data: { // VNode 構成項目を保存 attrs: { id: '#app' } }, context: componentContext, // コンポーネントスコープ elm: undefined, // 実際のDOM要素 children: [ { タグ: 'vue-component-1-test', children: undefined, // コンポーネントはページの最小単位であり、スロットコンテンツは子コンポーネントで解析されます parent: undefined, componentOptions: { // コンポーネント構成項目 Ctor: VueComponentCtor, // コンポーネント構築方法 data: { フック: { init: fn, //メソッド呼び出しコンポーネントをインスタンス化します insert: fn, プレパッチ: fn、 破壊する: fn }, scopedSlots: { //スコープスロット構成項目。スコープスロットVNodeを生成するために使用される スロット名: slotFn } }, children: [ // コンポーネントスロットノードタグ: 'template', propsData: undefined, // propsパラメータ listeners: undefined, データ: { スロット: 'hello' }, 子: [ VNode ], 親: 未定義、 context: componentContext // 親コンポーネントのスコープ // ... ] } } ]、 // ... } 7. サブコンポーネント状態の初期化サブコンポーネントをインスタンス化すると、サブコンポーネント スロット ノードは、 8. サブコンポーネントのコンパイルフェーズコンパイル フェーズでは、サブコンポーネントは { タグ: 'h1', 親: 未定義、 子供たち: [ { タグ: 'スロット', スロット名: "\"hello\"", // ... } ]、 // ... } 9. サブコンポーネント生成レンダリング方法生成されたレンダリング メソッドは次のとおりです。_t // レンダリングメソッド with(this){ _c('h1',[ _t("hello") ], 2) を返します } // ソースコードパス: vue-dev\src\core\instance\render-helpers\render-slot.js エクスポート関数renderSlot( 名前: 文字列、 フォールバック: ?Array<VNode>, 小道具: ?オブジェクト、 バインドオブジェクト: ?オブジェクト ): ?配列<VNode> { const scopedSlotFn = this.$scopedSlots[名前] ノードを if (scopedSlotFn) { // スコープ付きスロット 小道具 = 小道具 || {} if (bindObject) { process.env.NODE_ENV !== 'production' && !isObject(bindObject) の場合 { 警告( '引数なしのスロット v-bind はオブジェクトを期待します'、 これ ) } props = extend(extend({}, bindObject), props) } //スコープ スロット、スロット VNode を取得 ノード = scopedSlotFn(props) || フォールバック } それ以外 { // スロットの通常スロット VNode を取得します nodes = this.$slots[name] || フォールバック } const ターゲット = props && props.slot if (ターゲット) { this.$createElement('template', { slot: target }, nodes) を返します。 } それ以外 { ノードを返す } } スコープ付きスロットと名前付きスロットの違い <!-- デモ --> <div id='アプリ'> <テスト> <テンプレート スロット="hello" スロット スコープ='スコープ'> {{scope.hello}} </テンプレート> </テスト> </div> <スクリプト> var vm = 新しい Vue({ el: '#app', コンポーネント: テスト: { データ () { 戻る { こんにちは: '123' } }, テンプレート: '<h1>' + '<スロット名="hello" :hello="hello"></スロット>' + '</h1>' } } }) </スクリプト> スコープ スロットと通常のスロットの主な違いは、スロット コンテンツがサブコンポーネント スコープ変数を取得できることです。サブコンポーネント変数を挿入する必要があるため、スコープ スロットは名前付きスロットとは次の点で異なります。 レンダリング メソッドをアセンブルすると、スコープ スロットは注入スコープを含むメソッドを生成します。 (これ){ _c('div', { を返す 属性: { 「id」: 「アプリ」 } }, [_c('テスト', { スコープスロット: _u([{ キー: "hello", fn: 関数(スコープ) { [_v("\n " + _s(scope.hello) + "\n ")] を返します } }]) })], 1) } サブコンポーネントが初期化されると、名前付きスロットノードが処理され、コンポーネント それ以外は、プロセスはほぼ同じです。スロットの仕組みは理解するのが難しくありませんが、鍵となるのはテンプレートの解析とレンダリング関数の生成という 2 つのステップであり、これらはより複雑でプロセスが長く、理解するのがより困難です。 10. 使用上のヒント以上の分析により、スロット処理フローを大まかに理解することができます。ほとんどの作業はテンプレートを使用して 10.1. 名前付きスロットスロット処理は、一般的に次の 2 つの部分に分かれています。
<div id='アプリ'> <!-- <テスト>--> <!-- <テンプレートスロット="hello">--> <!-- 123--> <!-- </テンプレート>--> <!-- </テスト>--> </div> <スクリプト> 新しいVue({ // el: '#app', レンダリング (要素を作成) { createElement('test', [ を返します。 要素を作成します('h3', { スロット: 'hello', domProps: { 内部テキスト: '123' } }) ]) }, コンポーネント: テスト: { レンダリング(要素を作成) { createElement('h1', [ this.$slots.hello ] を返します。) } // テンプレート: '<h1>' + // '<スロット名="hello"></スロット>' + // '</h1>' } } }).$mount('#app') </スクリプト> 10.2. スコープ付きスロットスコープ付きスロットはより柔軟に使用でき、サブコンポーネントの状態を挿入できます。スコープ付きスロット + <div id='アプリ'> <!-- <テスト>--> <!-- <span slot="hello" slot-scope='scope'>--> <!-- {{scope.hello}}--> <!-- </span>--> <!-- </テスト>--> </div> <スクリプト> 新しいVue({ // el: '#app', レンダリング (要素を作成) { createElement('test', を返す。 スコープスロット:{ hello: scope => { // 親コンポーネントのレンダリングメソッドでは、最終的に変換されたスコープスロットメソッドはこの記述方法と一致しています return createElement('span', { domProps: { 内部テキスト: scope.hello } }) } } }) }, コンポーネント: テスト: { データ () { 戻る { こんにちは: '123' } }, レンダリング (要素を作成) { // スコープスロットの親コンポーネントは関数を渡します。この関数は手動で呼び出す必要があり、VNode を生成します。 slotVnode = this.$scopedSlots.hello({ hello: this.hello }) とします。 createElement('h1', [ slotVnode ]) を返します } // テンプレート: '<h1>' + // '<スロット名="hello" :hello="hello"></スロット>' + // '</h1>' } } }).$mount('#app') </スクリプト> 上記は、Vue スロットの実装原理の詳細な内容についての簡単な説明です。Vue スロットの詳細については、123WORDPRESS.COM の他の関連記事に注目してください。 以下もご興味があるかもしれません:
|
<<: 写真とテキストによる MySQL 8.0.11 インストール チュートリアル
ホスト 'xxxx' はこの MySQL サーバーに接続できませんエラー: 1130...
序文特に bash 環境では、スクリプトの実行方法によって結果が異なります。スクリプトを実行する方法...
目次1. プロジェクト統合1. CDNインポート方法: 2. 箱の梱包を確認する3. 迅速な箱詰め4...
序文CSS を使用して点線を生成するのは、フロントエンド開発者にとっては簡単です。一般的に、これを実...
序文ミニプログラムには、ユーザーを取得するための非常に便利な API があり、getPhoneNum...
Docker-ComposeとはCompose プロジェクトは、以前の fig プロジェクトから派生...
今日は、CSS 3.0 で実装されたネオン ボタン アニメーション効果を紹介します。効果は次のとおり...
フロントエンド開発では、スクロールバーを非表示にしながらスクロールをサポートしなければならないという...
1. まず、次のパスに従って対応するフォルダを作成します。 ローカルのdockerでmysqlを実行...
上の境界線のみを表示する <table frame=above>下の境界線のみを表示する...
DNSとはDNS の正式名称は Domain Name System で、ドメイン名解決システムを意...
目次序文: 1. データ移行について2. 移行計画と留意点要約:序文:日常業務では、テーブル、データ...
ポートマッピングDocker コンテナを起動する前にポート マッピングを行わないと、コンテナ外部のネ...
目次執筆の背景プロジェクトの説明事前準備注記執筆の背景以前のプロジェクトではTencent Maps...
成果を達成する 実装コードhtml <div class="wrapper"...