必要: バックグラウンド管理では、次のようなレイアウトでデータを表示する必要があることがよくあります。 これはテーブルのように見えますがテーブルではなく、フォームのように見えますがフォームではありません。実際、これはテーブルのように見え、表示されるデータはオブジェクトであり、フォームのバインドされた値と同じです。私はこれをフォームスタイルのテーブルと呼んでいます。 深いスタイルの列はタイトルで、浅いスタイルの列はタイトルに対応する値です。データはサーバーから返されることが多く、タイトルは固定幅であることが多いです。値は異なる場合があります。たとえば、画像を表示する場合、値は01で、はいまたはいいえを表示する必要があります。ユーザーが特定の値を変更できるように変更ボタンを追加する必要があり、列を複数の列にまたがるように設定する必要もあります。 まず、 不適切な実装: 引き継いだプロジェクトで実装を見ました。まずは使い方を見てみましょう。 <FormTable :data="lessonPackageArr" :fleldsInfo="lessonPackageInfo" :maxColumn="3" label-width="120px"> <テンプレート #presentedHours="{データ}"> <div class="flex-box between"> <span> {{ data.presentedHours }} </span> <span class="column-btn" @click="editPresentedHours(data)">編集</span> </div> </テンプレート> <テンプレート #gifts="{データ}"> <div class="flex-box between"> <span> {{データ.ギフト}} </span> <span class="column-btn" @click="editPresentedHours(data)">編集</span> </div> </テンプレート> </フォームテーブル> lessonPackageInfo オブジェクトの構造は次のとおりです。 // タイトル列とタイトル列に対応するフィールドを構成するために使用されるオブジェクト // type は値のタイプを指定します。これで、コンポーネントは内部的にどのタイプの値を表示できるかを設定します // サービスの場合、1 0 を返します。数値を表示する必要がある場合は、列をまたいでマップする map_data を提供します // 列属性設定を列間でマッピングします // スロットを提供するには、表示内容をカスタマイズする必要があります レッスンパッケージ情報: { orderType: { type: 'option', desc: 'コースパッケージカテゴリ', map_data: { 1: '初回注文', 2: '更新', 5: '無料コース' } }, combo: { type: 'text', desc: 'パッケージ名' }, presentationHours: { type: 'text', desc: '無料授業時間', slot: true }, 価格: { タイプ: 'テキスト'、説明: '標準価格' }, ギフト: { タイプ: 'text'、説明: 'ギフト'、列: 3、スロット: true }, }
コンポーネントの構成項目が多すぎるとなぜ悪いのでしょうか? この要件は非常に固定的です。コンポーネントの入力、つまり 完全にデータ駆動型でないことがなぜ悪いのでしょうか? このコンポーネントは完全にデータ駆動型ではありません。表示列をカスタマイズする必要がある場合は、テンプレートを作成する必要があります。 カスタマイズが必要な列が多数ある場合、テンプレートコードをたくさん記述する必要があります。再度抽出する場合は、コンポーネントを再度カプセル化するしかありません。抽出しない場合は、テンプレートコードが拡張される可能性があります。1行あたり500行の なぜ完全にデータ駆動型になる必要があるのでしょうか? コンポーネントを拡張するためのスロットはありますが、ビジネス コンポーネントを作成するときはそれらをあまり使用せず、代わりにデータ駆動型テンプレートを使用するようにしてください。データは js コードなので、コンポーネント コードが展開された場合、js コードを別のファイルに抽出するのは簡単です。スロット コードを抽出したい場合は、コンポーネントを再度カプセル化するだけです。
コンポーネントの使用に関する問題を確認した後、コンポーネント コードを確認しましょう。 <テンプレート> <div v-if="tableData.length" class="form-table"> <div v-for="(data, _) in tableData" :key="_" class="table-border"> <el-row v-for="(row, index) 行内" :key="index"> <el-col v-for="(フィールド、キー) 行内" :key="キー" :span="getSpan(field.column)"> <div v-if="(field.disabled && data[key]) || !field.disabled" class="column-content flex-box between"> <div class="label" :style="'width:' + labelWidth"> <span v-if="field.required" class="required">*</span> {{フィールド.desc}} </div> <div class="text flex-item" :title="データ[キー]"> <テンプレート v-if="key === 'minAge'"> <span>{{ データ[キー] }}</span> - <span>{{ データ['maxAge'] }}</span> </テンプレート> <テンプレート v-else-if="キー === 'ステータス'"> <テンプレート v-if="フィールド.ステータスリスト"> <span v-if="data[key] == 0" :class="field.statusList[2]">{{ field.map_data[data[key]] }}</span> <span v-else-if="データ[キー] == 10 || データ[キー] == 34" :class="field.statusList[1]"> {{ field.map_data[データ[キー]] }} </span> <span v-else :class="field.statusList[0]">{{ field.map_data[data[key]] }}</span> </テンプレート> <span v-else>{{ field.map_data[データ[キー]] }}</span> </テンプレート> <スロット v-else :name="キー" v-bind:data="データ"> <テーブル列コンテンツ :dataType="フィールドタイプ" :metaData="データ[キー]" :mapData="フィールド.map_data" :text="フィールドテキスト" /> </スロット> </div> </div> </el-col> </el-row> </div> </div> <div v-else class="form-table empty">データがありません</div> </テンプレート> <スクリプト> '@/components/TableColContent' から TableColContent をインポートします。 エクスポートデフォルト{ 名前: 'FormTable', コンポーネント: 表列コンテンツ、 }, 小道具: { // データ: { 必須: true、 タイプ: [オブジェクト、配列、null], }, // フィールド情報 fledsInfo: { 必須: true、 タイプ: オブジェクト、 // className: { type: "text", desc: "クラス名", column: 3 }, }, // 表示する列の最大数 maxColumn: { 必須: false、 タイプ: 数値、 デフォルト: 2, }, ラベル幅: { 必須: false、 タイプ: 文字列、 デフォルト: '90px'、 }, }, データ() { 戻る {} }, 計算: { テーブルデータ() { if (!this.data) { 戻る [] } if (this.data インスタンスの配列) { this.dataを返す } それ以外 { [this.data] を返す } }, 行() { 定数戻り配列 = [] 合計を0にする アイテムを{}とします (this.fleldsInfo の定数キー) { const nextTotal = 合計 + this.fleldsInfo[キー].column || 1 if (nextTotal > this.maxColumn) { returnArray.push(アイテム) アイテム = {} 合計 = 0 } 合計 += this.fleldsInfo[キー].column || 1 item[キー] = this.fleldsInfo[キー] 合計 === this.maxColumn の場合 { returnArray.push(アイテム) アイテム = {} 合計 = 0 } } if (合計) { returnArray.push(アイテム) } 戻り値 returnArray }, }, メソッド: { getSpan(列) { if (!列) { 列 = 1 } 列を返す * (24 / this.maxColumn) }, }, } </スクリプト> 質問は何ですか?
コードの一部: <span v-else-if="dataType === 'image' || dataType === 'cropper'" :class="className"> <el-popover placement="right" title="" trigger="hover"> <img :src="metaData" style="max-width: 600px;" /> <img slot="reference" :src="metaData" :alt="metaData" width="44" class="column-pic" /> </el-popover> </span> 上記の実装上の問題を分析した後、適切な実装を見てみましょう。 良い実装: まずは使い方を見てみましょう: <テンプレート> <ZmFormTable :titleList="タイトルリスト" :data="データ" /> </テンプレート> <スクリプト> エクスポートデフォルト{ 名前: 'テスト'、 データ() { 戻る { data: {}, // サーバーからtitleListを取得します: [ { タイトル: '名前'、プロパティ: '名前'、スパン: 3 }, { タイトル: 「教室作品」 プロパティ: (h, データ) => { 定数画像 = (データ.workPic && ( <エルイメージ スタイル='幅: 100px; 高さ: 100px;' src={data.workPic} プレビューソースリスト={[data.workPic]} </ElImage> )) || '' 画像を返す }, スパン: 3, }, { title: '仕事のコメント', prop: 'workComment', span: 3 }, ]、 } }, } </スクリプト> コンポーネントの説明: prop は パラメータ h と data はどのように渡されるのでしょうか?あるいは、この関数はどこで呼び出されるのでしょうか? h は 通常の関数の最初の引数が h の場合、それは この方法の方がはるかに簡単に使用できます。 内部実装を見てみましょう: <テンプレート> <div class="フォームテーブル"> <ul v-if="タイトルリスト.長さ"> <!-- titleInfo は変換された titleList です--> <li v-for="(item, index) in titleInfo" :key="インデックス" :style="{ 幅: ((item.span || 1) / titleNumPreRow) * 100 + '%' }" > <div class="form-table-title" :style="`width: ${titleWidth}px;`"> <Container v-if="typeof item.title === 'function'" :renderContainer="item.title" :data="data" /> <span v-else> {{ item.title }} </span> </div> <div class="form-table-key" :style="`width:calc(100% - ${titleWidth}px);`"> <Container v-if="typeof item.prop === 'function'" :renderContainer="item.prop" :data="data" /> <span v-else> {{ ![null, void 0].includes(data[item.prop] && data[item.prop]) || '' }} </span> </div> </li> </ul> <div v-else class="form-table-no-data">データなし</div> </div> </テンプレート> <スクリプト> './container.js' からコンテナをインポートします。 エクスポートデフォルト{ 名前: 'FormTable', コンポーネント: 容器、 }, 小道具: { タイトル幅: { タイプ: 数値、 デフォルト: 120、 }, タイトル番号前行: { タイプ: 数値、 デフォルト: 3, バリデータ: 値 => { const 検証 = [1, 2, 3, 4, 5, 6].includes(値) 検証する場合 console.error('titleNumPreRow は、行にタイトル フィールド ペアがあることを示します。これは 1 から 6 までの偶数のみで、デフォルトは 3 です') } 検証を返す }, }, タイトルリスト: { タイプ: 配列、 デフォルト: () => { 戻る [] }, バリデータ: 値 => { const 検証 = value.every(item => { const { タイトル、プロパティ } = アイテム タイトルとプロパティを返す }) 検証する場合{ console.log('渡された titleList 属性の要素には title 属性と prop 属性が含まれている必要があります') } 検証を返す }, }, データ: { タイプ: オブジェクト、 デフォルト: () => { 戻る {} }, }, }, } </スクリプト> <!-- スタイルは重要ではないので省略--> カスタム ディスプレイを実装する方法は、動的スロットを使用するのではなく、 エクスポートデフォルト{ 名前: 'コンテナ'、 機能的: 真、 レンダリング(h, {props}) { props.renderContainer(h, props.data) を返します。 }, }
要約:
レンダリング関数を使用して、拡張性の高いコンポーネントをカプセル化する方法についての記事はこれで終わりです。レンダリング関数を使用して、拡張性の高いコンポーネントをカプセル化する方法についての関連コンテンツについては、123WORDPRESS.COM で以前の記事を検索するか、以下の関連記事を引き続き参照してください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。 以下もご興味があるかもしれません:
|
<<: MySQL マルチバージョン同時実行制御 MVCC の基本原理の分析
>>: LinuxシステムにDockerをインストールするプロセス
1. システムインストールパッケージ yum -y インストール make gcc-c++ cmak...
目次保守可能なコードとは何ですか?コード規約1. 読みやすさ2. 変数と関数の命名3. 透過的な変数...
オンライン情報を参考に、cmakeを使用してCentOS6.8サーバーにMySQL5.7.18をイン...
1. MYSQLのインストール1. ダウンロードしたMySQLインストールファイルmysql-5.5...
この記事では、ドラッグ効果を実現するためのJavaScriptの具体的なコードを参考までに紹介します...
1. 現在、Pythonのバージョン管理ツールは数多く存在します。その中でも比較的使いやすいのがPy...
主キーを作成するには 2 つの方法があります。 テーブルテーブル名を作成( フィールド名タイプ、 フ...
著者は最近、仕事でパフォーマンスのボトルネックの問題に遭遇しました。MySQL テーブルには毎日約 ...
ステップ準備した静的リソースファイルを指定されたフォルダに配置しますnginx 設定ファイルを変更す...
SQLのlike文では、例えば SELECT * FROM user WHERE username...
元記事:究極の IE6 チートシート: 25 以上の Internet Explorer 6 のバグ...
目次1. 左端接頭辞原則2. 表に戻る3. インデックスプッシュダウン序文:インデックス プッシュダ...
目次概要ハッシュプロパティホストプロパティホスト名属性Href属性起源のプロパティユーザー名とパスワ...
この記事では、支払いの10秒カウントダウンを実現するためのJavaScriptの具体的なコードを参考...
img 画像タグに alt 属性を追加しますか?画像 img タグの alt 属性を見落とすことはよ...