Vue Elementのテーブルコンポーネントをカプセル化する方法

Vue Elementのテーブルコンポーネントをカプセル化する方法

Vue コンポーネントをカプセル化する場合でも、機能コンポーネントをクロスファンクショナルに使用します。関数コンポーネントに関しては、コンポーネント内の関数として考えることができ、入力パラメータはレンダリング コンテキストであり、戻り値はレンダリングされた HTML (VNode) です。これは、外側のコンポーネントが内側のコンポーネントの論理的なカプセル化にすぎず、レンダリングされたテンプレート構造があまり変更または拡張されず、ステートレスかつインスタンスレスである必要がある状況に適しています。ステートレスとは、作成、マウント、更新などの Vue ライフサイクル機能がないことを意味します。インスタンスレスとは、レスポンシブなデータとこのコンテキストがないことを意味します。

まずは Vue 機能コンポーネントの簡単な例から始め、その後この例に従って詳細を紹介します。

エクスポートデフォルト{
 機能的: 真、
 プロパティ: {},
 レンダリング(createElement、コンテキスト) {
   createElement('span', 'hello world') を返します
 }
}

Vue は機能スイッチを提供します。true に設定すると、コンポーネントをステートレスでインスタンスフリーの機能コンポーネントに変換できます。単なる関数なので、レンダリングのオーバーヘッドは比較的小さくなります。

関数コンポーネントの Render 関数には、createElement と context という 2 つのパラメータがあります。まず、最初のパラメータである createElement について理解しましょう。

簡単に言えば、createElement は仮想 DOM ノード VNode を作成するために使用されます。 3 つのパラメータを受け取ります。最初のパラメータは、DOM ノード文字列、Vue コンポーネント、または文字列や Vue コンポーネントを返す関数です。2 番目のパラメータはオブジェクトで、オプションであり、コンポーネントをレンダリングするために必要なパラメータを定義します。3 番目のパラメータは子仮想ノードで、createElement 関数によって作成されたコンポーネント、'hello world' などの通常の文字列、配列、または文字列や Vue コンポーネントを返す関数です。

createElement については注意すべき点がいくつかあります。

  • createElement の最初のパラメータがコンポーネントの場合、3 番目のパラメータは省略可能であり、記述しても無効になります。
  • レンダリング関数は、コンポーネント$emitによって発行されたイベントをonイベントでリッスンすることができます。
  • 2.3.0 より前のバージョンでは、機能コンポーネントが props を受け取る場合、 props オプションが必要でした。バージョン 2.3.0 以降では、props オプションを省略することができ、コンポーネントのすべての属性は自動的に暗黙的に props として解決されます。

関数コンポーネントの Render の 2 番目のパラメータはコンテキストです。データ、プロパティ、スロット、子、親はすべてコンテキストを通じてアクセスできます。

バージョン 2.5.0 以降では、単一ファイル コンポーネントを使用する場合、テンプレートベースの機能コンポーネントを <template functional></template> のように宣言できますが、Vue コンポーネント内に render 関数が存在する場合、Vue コンストラクターは template オプションまたは el オプションで指定されたマウント要素から抽出された HTML テンプレートからレンダリング関数をコンパイルしません。つまり、コンポーネント内で template 関数と render 関数が共存できません。コンポーネントに template がある場合、render 関数があっても、template オプションの方が render オプションよりも優先順位が高いため、render 関数は実行されません。

この時点で、Vue 関数コンポーネントの紹介はほぼ完了です。Element のテーブル コンポーネントが関数コンポーネントを通じてどのようにカプセル化されるかを見てみましょう。

効果画像:

1. カプセル化されたテーブルコンポーネント:

<テンプレート>
 <div>
  <el-table :data="cfg.data" style="width: 100%" v-on="cfg.on" v-bind="attrs" v-loading="読み込み中">
   <el-table-column v-if="cfg.hasCheckbox" v-bind="selectionAttrs" type="selection" width="55" label="xx" />
   <el-table-column v-for="cfg.headers 内の n" :prop="n.prop" :label="n.label" :key="n.prop" v-bind="{...columnAttrs, ...n.attrs}">
    <テンプレート スロット スコープ="{行}">
     <スロット:name="n.prop":row="行"><セル:config="n":data="行" />></スロット>
    </テンプレート>
   </el-table-column>
  </el-table>
  <el-ページネーション
   クラス="ページネーション"
   v-if="ページを表示"
   layout="total, sizes, prev, pager, next, jumper"
   :ページサイズ="[2, 3, 6, 11]"
   :page-size="ページサイズ"
   :total="ページ合計"
   :current-page="ページ.ページ"
   @current-change="ページを読み込む"
   @size-change="サイズ変更"
  />
 </div>
</テンプレート>

<スクリプト>
'./cell' からセルをインポートします

エクスポートデフォルト{
 コンポーネント:
  細胞、
 },
 小道具: {
  設定: オブジェクト、
 },
 データ(){
  戻る {
   読み込み中: true、
   列属性: {
    配置: '左'、
    サイズ変更可能: false、
   },
   cfg: {
    オン: this.getTableEvents(),
    属性: {
     境界線: true、
		   ストライプ: true、
    },
    データ: []、
    ...this.config、
   },
   ページ: {
    サイズ: this.config.size || 10,
    ページ: 1,
    合計: 0,
   },
   チェック済み: [],
  }
 },
 作成された(){
  これをロードします。
 },
 計算: {
  選択属性(){
   {selectable、reserveSelection = false} = this.config || {}、obj = {};
   // チェックボックスは選択可能か if(selectable && typeof selectable == 'function'){
    オブジェクト.assign(obj, {
     選択可能、
    })
   }
   //reserve-selection は type=selection の列に対してのみ有効です。タイプはブール値です。true の場合、データが更新された後も、以前に選択されたデータが保持されます (行キーを指定する必要があります)
   if(reserveSelection){
    オブジェクト.assign(obj, {
     'reserve-selection': reserveSelection、
    })
   }

   obj を返します。
  },
  属性(){
   {config: {spanMethod, rowKey}, cfg: {attrs}} を this とします。
   // セルを結合 - spanMethod は親コンポーネントから渡されたセルを結合する方法です。要素のセルの結合を参照してください if (spanMethod && typeof spanMethod == 'function') {
    オブジェクト.assign(attrs, {
     'span-method': spanMethod、
    })
   }
   // テーブルのページ全体を選択するには、row-key と reserve-selection を設定する必要があります。reserve-selection は、選択タイプである el-table-column にのみ設定できます。if(rowKey && typeof rowKey == 'function'){
    オブジェクト.assign(attrs, {
     '行キー': 行キー、
    })
   }

   属性を返します。
  },
  ページを表示(){
   {サイズ、合計} = this.page;
   合計サイズ < を返します。
  },
 },
 メソッド: {
  テーブルイベントを取得する(){
   {hasCheckbox = false} を this.config || {}、events = {}、_this = this とします。
   if(チェックボックスがある場合){
    // イベントをバインドする Object.assign(events, {
     '選択変更'(v){
     	_this.checked = v;
     },
    });
   }

   イベントを返します。
  },
  // チェックされた行を取得する getChecked(){
   this.checked を返します。
  },
  // リクエストデータ load(p = {}){
   {size、page} = this.page、{loadData = () => Promise.resolve({})} = this.config; とします。
   this.loading = true;
   // ここでの loadData のパラメータは、初期化時にページングに必要なページとサイズのみです。インターフェースに必要なその他のパラメータは、親コンポーネントの loadData で渡されます。loadData({...p, page, size}).then(({data, total}) => {
    this.cfg.data = データ;
    this.page.page = ページ;
    this.page.total = 合計;
    this.loading = false;
   });
  },
  ロードページ(インデックス){
   this.page.page = インデックス
   これをロードします。
  },
  sizeChange(サイズ){
   this.page.size = サイズ
   これをロードします。
  },
  // 通常、このメソッドはクエリボタンをクリックしたとき、またはテーブルリストを部分的に更新したときに呼び出されます。パラメータが渡されない場合は、デフォルトで最初のページからリロードします (p = {}) {
   このページ = 1
   これをロードします(p);
  },
 },
}
</スクリプト>

2. 要約テーブルの各列の Cell.js:

'./components' からコンポーネントとして * をインポートします。
空 = '-'
エクスポートデフォルト{
 小道具: {
  設定: オブジェクト、
  データ: オブジェクト、
 },
 機能的: 真、
 レンダリング: (h, c) => {
  let {props: {config = {}, data = {}}} = c, {prop, type = 'Default'} = config, value = data[prop] || config.value, isEmpty = value === '' || value === undefined;
  isEmpty を返します? h(Components.Default, {props: {value: empty}}) : h(Components[type], {props: {value, empty, data, ...config}});
 }
}

3. このカプセル化により、各列のレンダリングが複数の Vue コンポーネントに分割され、最終的にそれらが components.js ファイルにマージされてマッチングされます。

1) components.js ファイルを統合します。

'./Date' から Date をインポートします。
'./Default' から Default をインポートします。
'./Currency' から Currency をインポートします。
'./Enum' から Enum をインポートします。
'./Action' から Action をインポートします。
'./Link' から Link をインポートします。
'./Format' から Format をインポートします。
'./Popover' から Popover をインポートします。

輸出 {
 デフォルト、
 日付、
 通貨、
 列挙、
 アクション、
 リンク、
 形式、
 ポップオーバー、
}

2) 日付列 Date.vue

<テンプレート機能>
  <span>{{props.value | 日付(props.format)}}</span>
</テンプレート>

3) デフォルト列 Default.vue

<テンプレート機能>
  <span>{{props.value}}</span>
</テンプレート>

4) Currency.vue の金額の 1000 分の 1

<テンプレート機能>
  <span>{{props.value | 通貨}}</span>
</テンプレート>

5) 列のマッピング Enum.js

mapIdAndKey を list とします => list.reduce((c, i) => ({...c, [i.key]: i}), {});

STATUS = {とする
  順序: mapIdAndKey([
    {
      id: 'ドラフト',
      キー: 'CREATED'、
      val: '送信されていません',
    },
    {
      id: '保留中'、
      キー: 'IN_APPROVAL'、
      val: '審査中',
    },
    {
      id: '拒否'、
      キー: '拒否'、
      val: '承認が拒否されました',
    },
    {
      id: '拒否',
      キー: '拒否'、
      val: '承認が拒否されました',
    },
    {
      id: 'サイン',
      キー: 'CONTRACT_IN_SIGN'、
      val: '契約書への署名',
    },
    {
      id: 'signDone',
      キー: 'CONTRACT_SIGNED'、
      val: '契約書に署名しました',
    },
    {
      id: 'lendDone',
      キー: 'LENDED'、
      val: '融資成功',
    },
    {
      id: 'lendReject',
      キー: 'LOAN_REJECT'、
      val: '融資拒否'、
    },
    {
      id: 'キャンセル',
      キー: 'キャンセル'、
      val: 'キャンセルに成功しました',
    },
    {
      id: 'inLend',
      キー: 'IN_LOAN'、
      val: 'ローン承認進行中',
    },
  ])、
  モニター:mapIdAndKey([
    {
      キー: '00'、
      val: '監視されていません',
    },
    {
      キー: '01'、
      val: 'モニタリング',
    },
  ])、
}

エクスポートデフォルト{
  機能的: 真、
  render(h, {props: {値, Enum, 空}, 親}){
    enums = Object.assign({}, STATUS, parent.$store.getters.dictionary) とします。
      {name = '', getVal = (values, v) => values[v]} = Enum、_value = getVal(enums[name]、value);
      
    if(_value === undefined) の場合、h('span', _value === undefined ? 空の場合 : _value) を返します。

    {id, val} = _value とします。
    h('span', {staticClass: id}, [h('span', val)] を返します。
  }
}

6) アクション

const getAcitons = (h, 値, データ) => {
 結果 = value.filter(n => {
  {filter = () => true} = n とします。
  filter.call(n, data) を返します。
 });

 result.map(a => h('span', {class: 'btn', on: {click: () => a.click(data)}, key: a.prop}, a.label)) を返します。
}

エクスポートデフォルト{
 機能的: 真、
 レンダリング: (h, {props: {value, data}}) => {
  h('div'、{class: 'action'}、getAcitons(h、value、data) を返します)
 },
}

7) ジャンプ可能なリンクを持つ列Link.vue

<テンプレート>
 <router-link :to="{ パス、クエリ: パラメータ }">{{値}}</router-link>
</テンプレート>

<スクリプト>
エクスポートデフォルト{
 小道具: {
  データ: オブジェクト、
  値: 文字列、
  クエリ: {
   タイプ: 関数、
   デフォルト: () => {
    戻る {
     パス: ''、
     ペイロード: {}
    }
   }
  },
 },
 計算: {
  //ルートパス
  パス(){
   const { パス } = this.query(this.data)
   戻り経路
  },
  パラメータ(){
   const { ペイロード } = this.query(this.data)
   リターンペイロード
  },
 },
}
</スクリプト>

8) 表示したいデータ形式をカスタマイズするFormat.vue

<テンプレート機能>
 <div v-html="props.format(props.value, props.data)" />
</テンプレート>

9) コンテンツが多すぎる場合は、それを省略する必要があり、マウスを移動した後にプロンプ​​トウィンドウがポップアップし、すべてのコンテンツの列Popover.vueを表示します。

<テンプレート機能>
 <el-popover
  配置="トップスタート"
  幅="300"
  トリガー="ホバー"
  ポッパークラス="ポップオーバー"
  :content="props.value">
  <span slot="reference" class="popover-txt">{{props.value}}</span>
 </el-popover>
</テンプレート>
<スタイルスコープ>
.ポップオーバー-txt{
 オーバーフロー:非表示;
 テキストオーバーフロー:省略記号;
 空白:折り返しなし;
 表示: ブロック;
 カーソル: ポインタ;
}
</スタイル>

上記のコードからわかるように、render関数型に基づく機能コンポーネントとテンプレートに基づく機能コンポーネントの両方を使用しました。これは主にカプセル化の利便性のためです。結局のところ、コンパイラに最も近い関数であるrenderを使用するのは、少し面倒で、テンプレートに基づく機能コンポーネントほど便利ではありません。

4. カプセル化されたテーブルコンポーネントを使用する

1) スロットを使用しない場合:

<テンプレート>
 <div style="margin: 20px;">
  <el-button type="primary" v-if="excelExport" @click="download">選択したテーブルデータを取得します</el-button>
  <テーブル:config="config" ref="テーブル" />
 </div>
</テンプレート>

<スクリプト>
'@/components/table' からテーブルをインポートします。

エクスポートデフォルト{
 コンポーネント:
  テーブル、
 },
 データ() {
  戻る {
   設定: {
    ヘッダー: [
     {prop: 'contractCode', label: 'ビジネス番号', attrs: {width: 200, align: 'center'}},
     {prop: 'payeeAcctName'、label: '受取人口座名'、type: 'Link'、query: row => this.query(row)、attrs: {width: 260、align: 'right'}}、
     {prop: 'tradeAmt'、label: '支払額'、type: '通貨'},
     {prop: 'status'、label: '操作ステータス'、type: 'Enum'、Enum: {name: 'order'}}、
     {prop: 'statistic', label: 'Warning Statistics', type: 'Format', format: val => this.format(val)}, //表示するデータ形式をカスタマイズします {prop: 'reason', label: 'Reason', type: 'Popover'},
     {prop: 'payTime'、label: '支払時刻'、type: "日付"、format: 'yyyy-MM-dd hh:mm:ss'}, // フォーマットが設定されていない場合、デフォルトの日付フォーマットは yyyy/MM/dd です
     {prop: 'monitorStatus'、label: '現在の監視ステータス'、type: 'Enum'、Enum: {name: 'monitor'}}、
    ].concat(this.getActions())、
    //インターフェースを通じてリストデータを取得します - ここでのパラメーター p は、子コンポーネント loadData によって渡されるページングパラメーターです: p => request.post('permission/list', {...this.setParams(), ...p}),
    チェックボックスあり: true、
    選択可能: this.selectable、
    予約選択: false、
    rowKey: 行 => 行.id、
   },
   ステータス: "01",
   権限: ["handle", "pass", "refuse", "reApply", 'export']
  }
 },
 計算: {
  ハンドル() {
   this.permission.some(n => n == "handle") を返します。
  },
  合格() {
   this.permission.some(n => n == "pass") を返します。
  },
  拒否する() {
   this.permission.some(n => n == "reject") を返します。
  },
  拒否する() {
   this.permission.some(n => n == "refuse") を返します。
  },
  エクセルエクスポート(){
   this.permission.some(n => n == "handle") && this.permission.some(n => n == "export"); を返します。
  },
 },
 メソッド: {
  getActions(){
   戻り値: {prop: 'action'、名前: 'Operation'、タイプ: "Action"、値: [
    {ラベル: "表示"、クリック: データ => {console.log(data)}}、
    {ラベル: "処理"、クリック: データ => {}、フィルター: ({status}) => ステータス == 'CREATED' && this.handle}、
    {ラベル: "合格"、クリック: データ => {}、フィルター: ({status}) => status == '合格' && this.pass}、
    {ラベル: "拒否"、クリック: データ => {}、フィルター: ({ステータス}) => ステータス == '拒否' && this.reject}、
    {ラベル: "拒否"、クリック: データ => {}、フィルター: ({ステータス}) => ステータス == '作成済み' && this.refuse}、
   ]}
  },
  setParams(){
   戻る {
    名前: 'テスト'、
    ステータス: '01'、
    タイプ: 'CREATED'、
   }
  },
  クエリ(行){
   戻る {
    パス: '/otherElTable', // ルート パス
    ペイロード: {
     id: 行.id、
     タイプ: 'リンク'
    }
   }
  },
  フォーマット(val){
   str = '' とします。
   val.forEach(t => {
    str += '<span style="margin-right:5px;">' + t.total + '</span>';
   })
   str を返します。
  },
  選択可能({ステータス}){
   戻りステータス == "REFUSE" ? false : true
  },
  ダウンロード(){
   console.log(this.$refs.table.getChecked())
  },
 },
};
</スクリプト>
<スタイル>
.action span{margin-right:10px;color:#359C67;cursor: ポインター;}
</スタイル>

2) スロットの使用:

 <表:config="config" ref="表">
  <テンプレート #統計="{行}">
   <div v-html="loop(row.statistic)"></div>
  </テンプレート>
  <テンプレート #支払先口座名義="{行}">
   {{row.支払先口座名}}
  </テンプレート>
  <テンプレート #tradeAmt="{行}">
   {{row.tradeAmt | 通貨}}
  </テンプレート>
  <テンプレート v-slot:reason="{row}">
   <テンプレート v-if="!row.reason">-</テンプレート>
   <el-popover
    v-else
    配置="トップスタート"
    幅="300"
    トリガー="ホバー"
    ポッパークラス="ポップオーバー"
    :content="row.reason">
    <span slot="reference" class="popover-txt">{{row.reason}}</span>
   </el-popover>
  </テンプレート>
  <テンプレート #payTime="{行}">
   {{row.payTime | date('yyyy-MM-dd hh:mm:ss')}}
  </テンプレート>
  <テンプレート #customize="{行}">
   {{カスタマイズ(行.カスタマイズ)}}
  </テンプレート>
  <テンプレート #opt="{行}">
   <div class="アクション">
    <span>表示</span>
    <span v-if="row.status == 'CREATED' && handle">ハンドル</span>
    <span v-if="row.status == 'PASS' && pass">合格</span>
    <span v-if="row.status == 'REJECT' && deny">拒否</span>
    <span v-if="row.status == 'REFUSE' && decline">拒否</span>
   </div>
  </テンプレート>
 </表>

<スクリプト>
'@/components/table' からテーブルをインポートします。

エクスポートデフォルト{
 コンポーネント:
  テーブル、
 },
 データ(){
  戻る {
   設定: {
    ヘッダー: [
     {prop: 'contractCode', label: 'ビジネス番号', attrs: {width: 200, align: 'center'}},
     {prop: 'payeeAcctName', label: '受取口座名', attrs: {width: 260, align: 'right'}},
     {prop: 'tradeAmt', label: '支払額'},
     {prop: 'status'、label: '操作ステータス'、type: 'Enum'、Enum: {name: 'order'}}、
     {prop: '統計'、label: '早期警告統計'},
     {prop: 'payTime'、label: '支払い時間'},
     {prop: '理由', label: '理由'},
     {prop: 'monitorStatus'、label: '現在の監視ステータス'、type: 'Enum'、Enum: {name: 'monitor'}}、
     {prop: 'customize'、label: '表示をカスタマイズ'、type: 'Format'、format: val => this.customize(val)},
     {prop: 'opt'、label: '操作'},
    ]、
    ロードデータ: () => Promise.resolve({
     データ: [
      {id: 1、契約コード: ''、支払先口座名: '中国銀行上海支店'、取引額: '503869.265'、ステータス: '00'、支払時間: 1593585652530、
       統計:[
        {レベル: 3、合計: 5},
        {レベル: 2、合計: 7},
        {レベル: 1、合計: 20},
        {レベル: 0、合計: 0}
       ]、
       カスタマイズ: ['中国', '上海', '浦東新区']
      },
      {id: 2、契約コード: 'GLP-YG-B3-1111'、支払先口座名: '中国郵政上海支店'、取引額: '78956.85'、ステータス: '作成済み'、支払時間: 1593416718317、 
       理由: ポップオーバーのプロパティはツールチップのプロパティと非常に似ています。どちらも Vue-popper に基づいて開発されています。したがって、繰り返されるプロパティについては、ツールチップのドキュメントを参照してください。このドキュメントでは詳細には説明しません。 '、
      },
      {id: 3、契約コード: 'HT1592985730310'、支払先口座名: '中国招商銀行上海支店'、取引額: '963587123'、ステータス: 'PASS'、支払時間: 1593420950772、モニターステータス: '01'}、
      {id: 4、契約コード: 'pi239'、支払先口座名: '広州物流株式会社'、取引額: '875123966'、ステータス: '拒否'、支払時間: 1593496609363}、
      {id: 5、契約コード: '0701001'、支払先口座名: '建設銀行上海支店'、取引額: '125879125'、ステータス: '拒否'、支払時間: 1593585489177}、
     ]、
    })、
   },
   権限: ["handle", "pass", "refuse", "reApply", 'export'],
  }
 },
 計算: {
  ハンドル() {
   this.permission.some(n => n == "handle") を返します。
  },
  合格() {
   this.permission.some(n => n == "pass") を返します。
  },
  拒否する() {
   this.permission.some(n => n == "reject") を返します。
  },
  拒否する() {
   this.permission.some(n => n == "refuse") を返します。
  },
  エクセルエクスポート(){
   this.permission.some(n => n == "handle") && this.permission.some(n => n == "export"); を返します。
  },
 },
 メソッド: {
  クエリ(行){
   戻る {
    パス: '/otherElTable', // ルート パス
    ペイロード: {
     id: 行.id、
     タイプ: 'リンク'
    }
   }
  },
  ループ(val){
   if(!val) が '-' を返す
   str = '' とします。
   val.forEach(t => {
    str += '<span style="margin-right:5px;">' + t.total + '</span>';
   })
   str を返します。
  },
  カスタマイズ(v){
   vを返す?v[0] + v[1] + v[2]: '-'
  }
 }
}
</スクリプト>

2 つの異なる使用法があり、最初の使用法はスロットに基づかず、2 番目の使用法はスロットに基づきます。 2 つの方法を比較すると、2 番目の方法では、スロットを使用する列の type フィールドがヘッダー配列で定義されなくなったことがわかります。 type が定義されていても機能しません。 機能するのはスロットです。 さらに、操作列を接合するために concat が使用されなくなりました。 操作列もスロットを通じてレンダリングされます。 ただし、多くの列がスロットの形式で実装されている場合、ページはそれほどきれいに見えないと思います。

もう 1 つ、ほとんどのシナリオの実装はカプセル化されているため、スロットを使用するときにスロットを使用する必要はなく、ページをクリーンな状態に保つようにしてください。ヘッダー配列の後に操作リストを連結するのが少し面倒だと感じる場合は、操作リストをスロットの形式で実装してください。このブログで言及されているスロット実装は、より多くのオプションを提供するためのものです。

最後に、金額の 1000 分の 1 単位とタイムスタンプのフォーマットの実装については、ここではコードを投稿しません。自分で実装してください。

最近、カプセル化されたテーブルコンポーネントについて改めて考えてみたのですが、元のカプセル化をベースにした他の実装方法があるのではないかと考えました。例えば、元々定義されていたヘッダー配列の後に操作列を連結したくない、テーブルの特定の列のデータ処理方法が以前カプセル化した方法に含まれていない、このテーブルコンポーネントを初めて使用するフロントエンド開発者として、あなたの書き方に慣れていない、などです。あなたのカプセル化をベースに自分で処理方法をいくつか書いてもいいでしょうか?答えはイエスです。もちろん、コンポーネントがカプセル化されているので、誰もがルーチンに従い、時間と労力を節約できると言います。なぜそうしないのでしょうか?しかし、正直に言うと、学習の観点から、多くのスキルを持つ方が良いという考えから見れば、より多くを学び、より多く考え、より多くを行うことは常に私たちの進歩に有益です。ただ、実際の開発プロセスでは、パッケージング方法の選択に最善を尽くし、全員がこの合意に従う必要があります。

実際、こんなにナンセンスなことを言ってしまった後では、この変更はそれほど重要ではありません。元のパッケージに基づいてスロットを追加するだけです。このブログを読んだことがあるなら、カプセル化されたコードの中に、データの各列を処理するために特別に使用されるコード セクションがあることを覚えているはずです。
<Cell :config="n" :data="row" />
はい、それです。すでに上で紹介したので、これ以上は言いたくありません。今回の変更では主にスロットを使用します。

スロット API については、VUE の公式サイトやインターネット上のさまざまな記事で非常にわかりやすく説明されています。スロット API は、大まかに、デフォルト スロット (匿名スロットと呼ぶ人もいます)、名前付きスロット、スコープ スロットに分けられます。紹介については公式サイトやインターネット上の各種記事などをご参照ください。この変更では、主に名前付きスロットとスコープ付きスロットが使用されます。名前付きスロットは、その名前が示すように、名前の付いたスロットです。このカプセル化で使用するスロットの名前は、テーブルの各列のプロパティから取得されます。このカプセル化におけるスコープ スロットの主な役割は、子コンポーネントのスロットを介して親コンポーネントに値を渡すことです。その実装は、Vue 親コンポーネントが子コンポーネントに値を渡すのと多少似ていますが、2 つが異なる方法で値を受け取る点が異なります。全体として、この変更の実装は非常に簡単です。 <Cell :config="n" :data="row" />周りに名前付きスロットの別のレイヤーをラップするだけです。
<slot :name="n.prop" :row="row"><Cell :config="n" :data="row" /></slot>
それでおしまい。

次に、上で提起した質問に答えます。答えを見てみましょう:

<表:config="config" ref="表">
  <テンプレート #payTime="{行}">
   {{row.payTime | date('yyyy-MM-dd hh:mm:ss')}}
  </テンプレート>
  <テンプレート #customize="{行}">
   {{カスタマイズ(行.カスタマイズ)}}
  </テンプレート>
  <テンプレート #opt="{行}">
   <div class="アクション">
    <span>表示</span>
    <span v-if="row.status == 'CREATED' && handle">ハンドル</span>
    <span v-if="row.status == 'PASS' && pass">合格</span>
    <span v-if="row.status == 'REJECT' && deny">拒否</span>
    <span v-if="row.status == 'REFUSE' && decline">拒否</span>
   </div>
  </テンプレート>
</表>

上記は特別なケースであり、冒頭で説明した方法を使用したくない場合は、別の「特別サービス」を提供します。スロットを使用して自分でデータをレンダリングする場合は、ヘッダー配列で、タイプ フィールドを追加せずにテーブル ヘッダーのレンダリングを提供する必要があることに注意してください。
たとえば、テーブルの日付列を最初にレンダリングしたときは、次のように記述しました。
{prop: 'payTime', label: '付款時間', type: "Date", format: 'yyyy-MM-dd hh:mm:ss'}
したがって、スロットを使用して自分でデータをレンダリングする場合、ここでの記述は次のようになります。
{prop: 'payTime', label: '付款時間'}
また、以前はヘッダー配列の後に配列を連結して操作列を定義していました。スロットを使用して自分でデータをレンダリングする場合は、配列を再度連結する必要はありません。代わりに、ヘッダー配列に{prop: 'opt', label: '操作'}を追加するだけです。

実際、この変更は、スロットのレイヤーが元のベースで再パッケージ化されることを意味します。したがって、データを自分で処理する必要がなく、インターフェイスによって返されたデータを直接表示する必要がある状況では、このカプセル化されたテーブル コンポーネントを使用するときに特別な処理を行う必要はなく、上記のスロットのように定義する必要もありません。以前と同じように、ヘッダー配列で通常どおり定義するだけです。スロットのため、名前付きスロットまたはデフォルト スロットを定義しない場合、スロットに表示されるのは、スロット タグ スロットでラップされた<Cell :config="n" :data="row" />なります。
わかった?

もう 1 つ、日付や金額の 1000 分の 1 などの列を処理するためにスロットを使用しない場合は、上で紹介したスロットの原則に従って、ヘッダー配列で次のように定義できます。

{prop: 'tradeAmt'、label: '支払額'、type: '通貨'},
{prop: 'payTime'、label: '支払い時間'、type: "日付"},

ここまで書いてきて、私が本当に言いたいのは、スロットが追加されても、これまでの使用方法に基本的に影響はないということです。 これまでどおり、自由にお使いいただけます。 ただ、より多くの選択肢を提供しているだけです。

本当にスロットを使いたくない場合、ページをすっきりと保ちたい場合は、<Cell :config="n" :data="row" /> コードをスロットでラップするかどうかは関係ありません。上で紹介した最初の方法を使用するだけで済みます。

著者: 小淮

出典: http://tnnyang.cnblogs.com

以上が、Vue Element のテーブルコンポーネントをカプセル化する方法についての詳細です。Vue Element のテーブルコンポーネントのカプセル化の詳細については、123WORDPRESS.COM の他の関連記事に注目してください。

以下もご興味があるかもしれません:
  • Vue3 テーブルコンポーネントの使用
  • Vue Elementのテーブルコンポーネントをカプセル化する詳細な例
  • vxe-table vue テーブル テーブル コンポーネント 関数
  • Vue.js はソート可能なテーブルコンポーネント関数の例を実装します
  • Vue でシンプルなテーブルコンポーネントを実装する詳細な例
  • Vue 固定ヘッダー、固定列、クリック テーブル ヘッダー、ソート可能なテーブル コンポーネント
  • Vue.js テーブルコンポーネントの開発の詳細な例
  • Vue+elementuiはドロップダウンテーブルの複数選択と検索機能を実現します
  • vue+Element のテーブルは編集可能です (ドロップダウン ボックスを選択)
  • Vueはドロップダウンテーブルコンポーネントを実装します

<<:  初心者向けの一般的な Linux システムコマンドの完全なリスト

>>:  MySQLデータベースのトランザクション分離レベルの詳細な説明

推薦する

DockerでPrometheusをインストールする詳細なチュートリアル

目次1. Node Exporterをインストールする2. cAdvisorをインストールする3. ...

CSS を使用して三角形を実装する一般的な手法 (複数の方法)

面接の経験によっては、CSS に関する質問がよく見られ、CSS を使用して三角形を描画する方法につい...

CSSマウスを画像の上に置いたときにマスクレイヤー効果を追加する実装

まず効果を見てみましょう: マウスを画像の上に移動すると、影の効果とテキスト/アイコンが追加されます...

CentOS7 で MySQL データベースにリモート接続できない理由と解決策

序文最近、仕事で問題が発生しました。 Centos7 システムでは MySQL にリモート接続できな...

忘れられたMySQLパスワードとログインエラーの問題について簡単に説明します

MySQL ログイン パスワードを忘れた場合、解決方法は実はとても簡単です。MySQL メイン構成フ...

Vue で PC アドレスをモバイル アドレスにリダイレクトする方法

要件:PC側とモバイル側は2つの独立したプロジェクトです。2つのプロジェクトの内容は基本的に同じで、...

ウェブデザインにおけるポップアップウィンドウとフローティングレイヤーのデザイン

従来のソフトウェアから Web ウェアへの段階的な移行の傾向の中で、デザイン パターンとテクノロジは...

ウェブ開発者はIE7とIE8の共存を懸念している

今日、IE8 をインストールしました。ダウンロードするために Microsoft の Web サイト...

altとtitleの違いの詳しい説明

これら 2 つの属性はよく使用されますが、その違いはまとめられていません。それでは、その使い方をまと...

Element UI をインストールして vue3.0 でベクター グラフィックスを使用する方法

ここでは、v3 のインストールと使用にのみ焦点を当てます。v2 について学びたい場合は、公式 Web...

Dockerイメージの作成Dockerfileとコミット操作

イメージを構築するイメージを構築するには、主に 2 つの方法があります。実行中のコンテナをイメージに...

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

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

Dockerがコンテナを起動するたびに、IPとホストが指定した操作が実行されます。

序文Dockerを使ってHadoopクラスタを起動するたびに、ネットワークカードの再バインド、IPの...

MySQL で MHA アーキテクチャのデプロイメントを構築する手順

目次マハ1. MAHアーキテクチャの概要2. 適用可能なシナリオ3. MHAの動作原理4. MHAの...

Vue プロジェクトで mock.js を使用するための完全な手順

Vue プロジェクトで mock.js を使用する開発ツールの選択: Vscode 1. コマンドラ...