100 左右實現查詢表格?真的假的?一起來體驗一下 Amiya 的魅力。

viewweiwu發表於2022-03-02

image.png

“老哥,聽說你寫的頁面挺多的,我這兒有一個頁面,你覺得你需要多少程式碼?”

“我看看,也還行吧,不就是個查詢表格嘛,現在大家都用 ProComponent 了,用那個寫一下很快的。我想想,差不多 200 行左右就可以了吧。”

“那個呀,我知道,官方的二次封裝元件庫,200 行就可以了嗎?嗯,可以。等等,你說的程式碼是否包含了操作按鈕?”

“操作按鈕?是指你圖上的 【新增】【詳情】這些按鈕嗎?”

“是啊。”

“點了之後長啥樣呀,你也沒給我看呀!”

“哦,差不多長這個樣。”

image.png

“哦~ 這樣子啊,那這個簡單,不就是個彈窗表單嘛,撐死再加個 100 行吧。”

“那【刪除】呢?”

image.png

“就這。10 行就搞定了吧。”

“哈哈,你彆著急嘛,還有批量刪除呢!”

image.png

“哦哦,這也沒多難啊,大部分都是表格自帶的 Api,刪除完重新整理下表格請求就完事兒了。無非就是記錄下選項嘛,再給個 10 行我覺得就差不多了。不過我看你這勾選之後,頁面下面還有個條,把【批量刪除】按鈕放那裡了,有點意思,不過也沒多難,再加個 20 行左右我覺得差不多了。”

“哈哈,是的,我算算,這差不多已經 340 行了吧。”

“是啊,寫這樣一個頁面的話,這點程式碼量很正常。”

“那如果翻頁後,仍然保留上個頁面的選項呢?”

“這個呀,現在哪有人做這個呀,這都是現成的元件,你不嫌麻煩我還嫌麻煩呢,而且又不是必須的,愛誰誰做。”

“你就說你會不會吧!”

“你是故意找茬是吧!再說了,這也不難,antd 表格不是有個 preserveSelectedRowKeys 屬性嗎,我覺得可以用那個實現,或者監聽下表格的選擇事件,存個變數就好了。實在不行,就點頁面單個刪除唄,也沒多麻煩吧。”

“說是這麼說,確實也沒必要,但我覺得有更好,如果要刪除多個的話,每次刪除總是要多點幾次,而且刪除完之後,資料不是沒了嘛,那第二頁的資料就會跑到第一個頁面來,就會擔心自己會不會刪錯。”

“還行吧,只要你不嫌累,你就寫吧。我覺得也沒啥,如果真要做,用那個 api 就好了,頂多再加個 20 行吧。”

“哦!對了,我忘記說了,這個數字懸浮上去是能看到選項的。”

image.png

“...你玩的還挺花,資料都有,搞個 Popover 套一下,就可以了吧。”

“是的,這麼樣一算的話,差不多有 400 行程式碼了吧。”

“嗯,你需求多嘛,差不多差不多。”

“哈哈,這個頁面我總共花了 134 行程式碼,你覺得可行

“???你怎麼做到的,給我看看。“

檢視錶格示例程式碼

“我看了一下,有意思,這個元件用了一個大 json,把配置傳進去了是吧,這種封裝還挺常見的。”

“是的,你看這是其中一個片段,表格的頂部查詢,只需要指定 search: true 就可以了。”

{
  title: '英文名',
  key: 'en'
  search: true
}

“這樣子啊,那上面我看有 placeholder 呀,怎麼沒看你傳進去。”

“哦,那個是自動生成的,像這裡,會生成"請輸入英文名"。”

“那如果要自定義呢?”

“當然也可以,需要這樣子寫。”

{
  title: '英文名',
  key: 'en'
  search: {
    placeholder: '請輸入英文名'
  }
}

“哦~ 這還能是個物件是吧,那如果上面是個選擇框呢?”

“也簡單,新增 optionstype: 'select' 就可以了。”

{
  title: '職業',
  key: 'class',
  type: 'select',
  options: [
    { label: '近衛幹員', value: '1' },
    { label: '狙擊幹員', value: '2' },
    { label: '術師重灌', value: '3' },
    { label: '醫療幹員', value: '4' },
    { label: '重灌幹員', value: '5' },
    { label: '輔助幹員', value: '6' },
    { label: '特種幹員', value: '7' },
    { label: '先鋒幹員', value: '8' }
  ],
  search: true
}

“你這 optionstype 為什麼沒有放在 search 物件裡面的呀?”

“哈哈,這你就不知道了吧,因為這樣子寫的話,表格也可以用這個配置,寫在 search 物件裡面的話,就只能查詢區域自己用了。”

“表格也可以用這個配置?表格要這倆有啥用。”

“表格這一列,可以通過 options 翻譯,假如資料是個 1,那麼這一列就會根據 options 去尋找這個 label,這時候對應的 label近衛幹員,所以頁面上顯示的就是 近衛幹員。另外如果表格有篩選,新增 filter: true 就會出現篩選了。”

image.png

“可以,還挺方便的,那 type 呢?這東西表格用不到吧。”

“是的,這個的話,其實是給 dialog 彈窗編輯用的。這樣子的話可以讓彈窗裡面也展示一個選擇框了。”

{
  title: '職業',
  key: 'class',
  type: 'select',
  options: [
    { label: '近衛幹員', value: '1' },
    { label: '狙擊幹員', value: '2' },
    { label: '術師重灌', value: '3' },
    { label: '醫療幹員', value: '4' },
    { label: '重灌幹員', value: '5' },
    { label: '輔助幹員', value: '6' },
    { label: '特種幹員', value: '7' },
    { label: '先鋒幹員', value: '8' }
  ],
  search: true,
+ dialog: true
}

“哦哦!明白了,指定了 dialog: true 後,就會在彈窗裡面顯示了是吧。”

“是的,那如果只在彈窗裡展示,而表格不展示呢?”

“那可以這樣子做。指定 table: false 就可以了。”

{
  title: '職業',
  key: 'class',
  type: 'select',
  options: [
    { label: '近衛幹員', value: '1' },
    { label: '狙擊幹員', value: '2' },
    { label: '術師重灌', value: '3' },
    { label: '醫療幹員', value: '4' },
    { label: '重灌幹員', value: '5' },
    { label: '輔助幹員', value: '6' },
    { label: '特種幹員', value: '7' },
    { label: '先鋒幹員', value: '8' }
  ],
  dialog: true,
+ table: false
}

“明白了。這是把彈窗、表格、查詢揉在一起了是吧,對了,我怎麼沒有看到新增開啟彈窗的程式碼呢?”

“那個呀,那個需要再加點程式碼。把 addApi 作為請求介面傳進去,再指定 action="add" 就好了?”

<AySearchTable
  title="Amiya 增刪改查"
  dialogFormExtend={{
    fields: fields,
    addApi
  }}
>
  <AyAction action="add">新增</AyAction>
</AySearchTable>

“這也可以?為什麼?難到不需要監聽按鈕點選事件,然後控制彈窗顯示,再請求介面,之後關閉彈窗重新整理頁面嗎?”

“是的,這裡預設認為彈窗和表格共用一個配置,且彈窗新增大多都是千篇一律的,所以把所有的操作封裝了一下,就只剩下這麼點了。當然如果太過複雜,或者跟表格都沒有什麼可以共用的列,就再定義一個 'fields: dialogFields',和表格完全分開用倆 fields,各用各的。”

“哦哦,可以可以,那我理解了,修改也是同理吧。”

“是的,編輯的時候,不是會有預設值嗎?此時我們把 record 傳進去,當作表單的預設值就可以了。”

const ctrl: AyTableCtrlField = {
  render: (value: string, record: Record) => {
    return (
      <AyCtrl>
        <AyAction record={record} action="update">
          編輯
        </AyAction>
      </AyCtrl>
    )
  }
}

<AySearchTable
  title="Amiya 增刪改查"
  dialogFormExtend={{
    fields: fields,
    addApi
  }}
/>

“可以,可以!這個元件把常用的操作都變成指令了啊。”

“是的呀,如果你的詳情是需要請求介面的,那就不需要 record 了,刪掉之後改成 detailApidetailParams, 分別是請求的介面和請求的引數,action="view" 指令會自動的把請求返回的資料,作為開啟彈窗後表單的預設值的。”

<AyAction detailParams={record.sort_id} detailApi={detailApi} action="view">詳情</AyAction>

“明白了,非常的棒!對了你剛剛還說到分頁刪除了,用這個元件是不是也很簡單啊?”

“是的,我給你看一下,這個多個幾步,第一步,先新增 selectionType="checkbox" 開啟勾選;第二步,新增 selectShowKey="cn",讓氣泡懸浮時用它來決定展示選中的名稱,並用 tag 標籤裹住,因為 tag 標籤可以刪除的,這樣子翻頁之後也可以點選 tag 標籤上面的 X,來取消選項,不用再翻到上一頁取消選擇了;第三步,在刪除按鈕上新增 action="delete" 屬性,批量刪除上新增 action="batch-delete" 屬性,標籤上新增 deleteApi={deleteApi} 介面,就可以完成刪除和批量刪除的動作了。”

const ctrl: AyTableCtrlField = {
  render: (value: string, record: Record) => {
    return (
      <AyCtrl>
        <AyAction record={record} action="delete">
          刪除
        </AyAction>
      </AyCtrl>
    )
  }
}

<AySearchTable
  title="Amiya 增刪改查"
  selectionType="checkbox"
  rowKey="sort_id"
  ctrl={ctrl}
  selectShowKey="cn"
  deleteApi={deleteApi}
>
  <AyAction action="batch-delete">批量刪除</AyAction>
</AySearchTable>

“哦哦,這樣子就可以了嗎?那還挺方便的,畢竟不需要自己寫一堆程式碼來寫。對了,我剛才看了下程式碼,上面有個 renderType: 'html',這是什麼作用。”

{
  title: '描述',
  key: 'feature',
  width: 200,
  renderType: 'html'
}

“你猜猜?”

“把這一列渲染成 html 之類的?”

“是呀,除此之外,還有 unit datetime state 等等型別,你可以看看這個。”

檢視自定義型別

“可以,那如果我要的這裡面沒有呢?”

“就等著你問這個呢,看來你用過其它的二次封裝呀,這個元件提供兩種方式,第一種可以指定 render 方法。”

{
  title: '姓名',
  key: 'cn',
  search: true,
  dialog: {
    required: true
  },
  table: {
    // 渲染自定義內容
    render: (text: string, record: Record) => {
      return (
        <div>
          <div>{record.cn}</div>
          <div>{record.en}</div>
          <div>{record.jp}</div>
        </div>
      )
    }
  }
},

“第二種,可以全域性註冊,註冊完之後,可以像 renderType: 'star' 這樣子使用。”

import { registerTableRender, RenderProps } from 'amiya'

/**
 * @decs 註冊 renderType
 * @param renderTypeName string 註冊型別名字
 * @param text string 當前 col 的資料
 * @param record object 當前 row 的資料
 * @param field 當前配置配置項
 *
 * @returns ReactNode
 */
registerTableRender('renderTypeName', ({ text, record, field }: RenderProps) => {
  return <span>{text}</span>
})

// 實際使用
const fields = [
  {
    renderType: 'renderTypeName' // 已經註冊過後的名字
  }
]

註冊自定義表單型別

“好傢伙,這跟我直接 render 也沒什麼區別嘛,不過用註冊的方法,把 render 寫在其它公共的地方的話,確實會讓當前頁面乾淨一點。”

“是的,兩種方式自由選擇。你看這樣子一套下來,你看,是不是省了很多程式碼,如果你用 jsx 語法糖的話會更省,那樣子只需要 90 行程式碼了。”

“對哦,我見到的其它二次封裝就是少了這個,都用 json,用起來編輯器右邊空白一大片,程式碼又拉的老長,挺不爽的,你這樣子寫法我挺喜歡的,我跟他們提建議,他們都不聽的,還云云這樣容易控制什麼的。”

 <AyFields>
   <AyField
     title="頭像"
     key="icon"
     width={80}
     align="center"
     renderType="image"
   />
   <AyField title="姓名" key="cn" search />
   <AyField title="英文名" key="en" search dialog table={false} />
   {// ...}
 </AyFields>

“真能省,還沒見過這麼能省的,不過,這個元件封裝的這麼多,別人會用嗎?用的明白嗎?”

“確實,如果不介紹介紹的話,沒人用的明白。所以這個元件支援完整的 TypeScript 提示,也準備了文件,詳細地介紹了表格的使用方式,你看左側那一堆選單,都是在介紹表格 api 的。”

image.png

“而且,也有完整的頁面級別的示例,也可以做參考。”

表格其它示例

“我看到了,這是個二次封裝的元件庫吧,我看還有其它元件,等我回頭用用看體驗一下。”

“好的,等你訊息。”

Amiya 二次封裝文件地址

相關文章