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データベースのトランザクション分離レベルの詳細な説明

推薦する

html2canvas で破線境界線を実装する例

html2canvas は、HTML 要素からキャンバスを生成するライブラリです。描画されるキャンバ...

Firefox の CSS を使用してデータを盗む

0x00 はじめに数か月前、Firefox に脆弱性 (CVE-2019-17016) があること...

ES6実装クラスのプライベート変数の書き方をいくつか詳しく説明します

プライベート変数のクロージャ実装プライベート変数は共有されないnew キーワードにより、 perso...

ウェブページのメモリとCPU使用量を削減する方法

<br />Web ページによっては、サイズは大きくないように見えても開くのに非常に時間...

Vueカスタムディレクティブの詳細

目次1. 背景2. ローカルカスタム指示3. グローバルカスタム指示4.1 カスタムコマンドフック関...

nofollowタグの使用と分析に関する簡単な説明

nofollowをめぐる論争Zac と Guoping の間では、nofollow が PR を無駄...

CentOS7におけるKVM仮想化の基本管理の詳しい説明

1. kvm仮想化をインストールする : : : : : : : : : : : : : : : :...

Web ページでパラメータ名によって ActiveX コントロールのプロパティに値を割り当てる例

コードをコピーコードは次のとおりです。 <HTML> <ヘッド> <T...

MySQLシリーズのMariaDBサーバーのインストール

目次チュートリアルシリーズ1. yumパッケージマネージャーを使用してMariaDBサーバーをインス...

CentOS 6.5 の設定 ssh キーフリーログインで pssh コマンドを実行する方法の説明

1. psshを確認してインストールします。yum list pssh 2. キーレスログインが設定...

docker-compose で Jenkins をインストールする際の実践的なメモ

ディレクトリを作成する cd /usr/local/docker/ jenkins-docker を...

24 の実用的な JavaScript 開発のヒント

目次1.配列を初期化する2. 配列の合計、最大値、最小値3. エラー値をフィルタリングする4. 論理...

SQLでEXPLAINコマンドを使用する方法

日常業務では、実行に時間のかかる SQL ステートメントを記録するために、スロー クエリを実行するこ...

JavaScriptのvar let constの違いは何ですか?

目次1. 繰り返し宣言1.1 変数1.2 しましょう1.3 定数2. 可変プロモーション2.1 変数...

https ウェブサイトを展開し、Nginx でアドレス書き換えを構成するための詳細な手順

Nginx は、高性能な Web サイト サーバーおよびリバース プロキシ サーバーであり、IMAP...