如何封裝業(yè)務(wù)組件 多行編輯功能

之前寫了個小組件, 首先感謝大佬們提的意見, 今天我要總結(jié)一下關(guān)于開發(fā)過程中, 什么情況下我們要去封裝自己的組件, 當(dāng)然這個我自己一步步感覺出來的, 大家可能也有自己的經(jīng)驗(yàn), 如果大家有更好的方法, 也希望大家可以不吝賜教留言給我和不小心進(jìn)來的同學(xué)

好了不多bb, 這次我是來解析封裝多行編輯組件的

多行編輯組件, 一般在管理系統(tǒng)的大表單中出現(xiàn)的幾率比較大, 而且業(yè)務(wù)越復(fù)雜的表單越有幾率出現(xiàn)他的身影, 部分人可能還沒聽過這個東西, 我先介紹一下吧, 這個東西也叫"動態(tài)增減表單項(xiàng)", 就是這個東西

list1.png

再element-ui中是這樣的

list2.png

網(wǎng)上對這個東西的介紹只能算一般多吧, jquery封裝的組件可能多一點(diǎn), 框架的UI雖然也有封裝, 但是功能都偏少

好了現(xiàn)在又到了我們會1+1, 就要算微積分了的時候了, 當(dāng)然我們也不能憑空去算, 至少看一下前人的經(jīng)驗(yàn), 我看過稍微完整一點(diǎn)的就是Ant Design Pro管理系統(tǒng)模板的, 當(dāng)然這個是react的, 但是無所謂是用的什么框架, 我們先看一下他的

list3.png

功能挺多的了, 而且他是在表格中實(shí)現(xiàn)的, 看起來比較整齊, 當(dāng)然用Layout布局也可以, 都沒什么問題, 我這次就站在巨人肩膀上用element-ui的表格布局實(shí)現(xiàn)以下他這個吧, 畢竟我們要做vue的多行編輯功能, 先總結(jié)他的已有功能吧, 然后我再添加點(diǎn)

總結(jié):

a. 有個表頭, 或者叫列名, 當(dāng)然我們在接下來的輸入框中我們還會繼續(xù)給他提醒
b. 要有一個操作列, 5種功能
i. 添加: 當(dāng)一個新的一行出現(xiàn)的時候展示, 填完信息后點(diǎn)擊添加變?yōu)椴豢删庉嫚顟B(tài)
ii. 刪除: 刪除當(dāng)前行
iii. 編輯: 當(dāng)已經(jīng)點(diǎn)過添加, 變?yōu)椴豢删庉嬔b填展示, 點(diǎn)擊后變?yōu)榭删庉嫚顟B(tài)
vi. 保存: 編輯后進(jìn)行保存數(shù)據(jù)
v. 取消: 取消當(dāng)前編輯的內(nèi)容, 類似于一個還原, 然后并變?yōu)椴豢删庉嫚顟B(tài)
c. 要有一個添加一行的功能
d. 最主要的就是中心編輯展示部分, 一種是展示狀態(tài), 不可編輯, 純文本, 一種是輸入框狀態(tài), 可編輯

好, 有了整理我們就很清楚了, 具體什么用什么功能的組件, 但是這些并不能滿足我們的需求, 我們還要再添加一點(diǎn)功能

新增:

a. 表單驗(yàn)證功能, 其實(shí)就是element-ui的那個多行編輯的驗(yàn)證功能, 讓他稍微變得靈活一點(diǎn)
b. 增加日期框, 數(shù)字輸入框, select框, 查詢回顯框(就用我之前寫的那個), 不過這樣會讓這兩個組件綁定言重, 但是這個對于我的業(yè)務(wù)來說是很有必要的, 雖然嚴(yán)重但是對我構(gòu)建項(xiàng)目來說卻更加便利

這里也引出一個點(diǎn), ui庫已經(jīng)給你封裝好了你就復(fù)制粘貼嵌套一下就好了, 為什么還要多此一舉?

我大體來回答一下, 我們的開發(fā)與封裝就是要基于業(yè)務(wù)和開發(fā)便利以及便于維護(hù)為目的, 而ui框架的開發(fā)更多的是為了去適應(yīng)更多的人使用, 更加便利易懂
打個比喻: ui庫不是做出一個個"人", 而是要做出一個個骨架, 一種種外貌, 讓我們自己去捏人捏臉, 讓我們自己拼接
而融入到業(yè)務(wù)中, 我們在這樣是不能夠達(dá)到最大方便的, 我們在業(yè)務(wù)中就是要吧這些零散的骨架適當(dāng)組裝, 組裝出可能用到的各種腿, 各種胳膊, 身子, 美麗且滿滿頭發(fā)的腦袋瓜, 我們再去拿這些拼人就好了, 原來我們要ui的零散的好多拼成一個頁面, 現(xiàn)在我們只要拿幾個稍大的功能組件一組就夠了, 可能很多人在自己的開發(fā)中已經(jīng)應(yīng)用了這種方法, 沒問題, 我覺得這么做有點(diǎn)棒棒的

開始操作起來, 不過我相信你已經(jīng)明白該怎么做了, 下面還是按照上一篇文檔的節(jié)奏來寫, 我們現(xiàn)在已經(jīng)總結(jié)完功能了, 接下來我們就是要設(shè)計(jì)基本的結(jié)構(gòu)

1. 基本結(jié)構(gòu)

<div>
  <table>
    <!-- 表頭 -->
    <thead>
      <td></td> *n
    </thead>
    <!-- 內(nèi)容 -->
    <tr>
      <td> *n
        <input>
      </td> 
      <!-- 控制列 -->
      <td>
        <button>確認(rèn)</button>
        <button>取消</button>
        <button>刪除</button>
        <button>編輯</button>
      </td>
    </tr>
  </table>
  <button>新增一行</button>
</div>

*n的地方代表了接下來我們要用循環(huán)創(chuàng)建

把結(jié)構(gòu)一屢, 沒多少東西, 接下來我們就要確定哪些東西是要外部控制的

2. 外部傳輸?shù)姆椒?/h3>

先插入一點(diǎn)原理, 這個多行編輯是怎么實(shí)現(xiàn)的
再vue中, 我們通過v-for循環(huán)創(chuàng)建一組對應(yīng)的標(biāo)簽, 所以如果我們對循環(huán)的那個變量不斷的push新的值自然就會被v-for渲染到頁面, 好了繼續(xù)整理

a. 首先傳入一個新增一行的方法, 上面介紹了, 我們只要給v-for遍歷的那個變量push就好了

b. 要傳入控制當(dāng)前行狀態(tài)的方法, 這個添加就是要當(dāng)我們完成單行編輯的時候, 先去驗(yàn)證是否必填的已經(jīng)填完了, 然后讓此行變成確定狀態(tài), 不可再編輯, 也可反之變?yōu)榭删庉嫚顟B(tài)

c. 傳入一個刪除的方法, 刪除就是從那個遍歷的參數(shù)中把當(dāng)前行的內(nèi)容刪除就可以了, 我們可以通過給每一行多定義一個隱藏參數(shù)為時間戳, 讓每一行保持獨(dú)立

d. 傳入取消的方法, 我們當(dāng)再修改途中, 想還原之前填寫的狀態(tài)用, 所以我們還要暫存一下當(dāng)前點(diǎn)擊修改的那行初始值

簡單寫一下這個

methods:{
  pushlist() {
    //添加一行
  },
  editstatus(index){
    //控制單行的開關(guān)狀態(tài)
  },
  delrow(index) {
    //刪除本行
  },
  cancelrest(index, sw, row) {
    //取消時恢復(fù)本行
  },
}

整理了方法, 我們就要看看這些方法中, 以及應(yīng)用中要用到哪些從外部傳入的參數(shù)呢

3. 外部傳入?yún)?shù)

a. 要傳入一個表頭的數(shù)組

b. 要傳入一個單行內(nèi)要有幾列, 也就是一行有幾個輸入框的數(shù)組, 這個比較麻煩我們要慢慢整理

c. 要傳入整個多行編輯數(shù)據(jù), 初始就是個空數(shù)組

4. 接下來把結(jié)構(gòu)補(bǔ)全

<div id="inputList">
<!-- 因?yàn)橐鰎ule驗(yàn)證, 所以要有form -->
  <el-form :model="listModel">
  <!-- 表格, tableData為多行編輯的數(shù)據(jù), 我們要用他的長度渲染表格有幾行所以要綁定data -->
    <el-table :data="listModel.tableData" style="width: 100%" size="mini">
    <!-- 在element-ui中的table是自動綁定列名稱的勺拣,所以就合成一個數(shù)組rowTable中 -->
      <el-table-column v-for="(item,index) in rowTable" :key="index" :label="item.label" :width="item.width">
      <!-- 要獲取單行數(shù)據(jù)進(jìn)行處理朋譬, 所以要綁定scope -->
        <template slot-scope="scope">
        <!-- 當(dāng)只展示時署鸡, 用span進(jìn)行展示 -->
          <span v-show="scope.row.status">{{ scope.row[item.prop] }}</span>
          <!-- 編輯時敬飒, 用form + input等方式編輯 -->
          <el-form-item v-show="!scope.row.status" :prop="'tableData.'+scope.$index+'.'+item.prop" :rules="item.rule"
            :ref="'tableData.'+scope.$index+'.'+item.prop">
            <el-input size="mini" v-model="listModel.tableData[scope.$index][item.prop]"
              v-if="item.type == 'text' || !item.hasOwnProperty('type')" :disabled="item.disabled"></el-input>
          </el-form-item>
        </template>
      </el-table-column>
      <!-- 單獨(dú)一列, 操作列 -->
      <el-table-column label="操作">
        <template slot-scope="scope">
          <el-button size="mini" @click="handleEdit(scope.$index, scope.row.status, scope.row)">
            {{scope.row.status?'編輯':'確定'}}</el-button>
          <el-button size="mini" type="danger" @click="handleDelete(scope.$index)">刪除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 新增一行操作 -->
    <el-button size="mini" @click="addRowList" class="addBtn">新增一行</el-button>
  </el-form>
</div>

5. 把需要循環(huán)創(chuàng)建的參數(shù)提取出來設(shè)計(jì)參數(shù)

a. rowTable, 看看循環(huán)他我們需要從中拿到那些數(shù)據(jù)來用, 把這些數(shù)據(jù)一總結(jié)放到個對象里, 這個就創(chuàng)建完了

{
  //顯示的名稱
  label: "郵箱",
  //input寬度
  width: "180",
  //綁定prop
  prop: "email",
  //驗(yàn)證規(guī)則
  rule: [{ required: true, message: "年齡不能為空" }],
  //input類型 "number", "date", "text", "search", "select", 暫時想了這么多, search就是上一篇的類型
  type: "number",
  //是否允許編輯, 有的內(nèi)容是只由別的帶出來, 只能看或者修改別的框改變這個, 所以此框禁用
  disabled: false
  },

b. tableData這個是自動綁定的, 我們要思考除了表格內(nèi)容我們還要什么參數(shù)

// form綁定的數(shù)據(jù)
listModel: {
  //表格綁定的數(shù)據(jù)
  tableData: [
    {
      //表格一行的數(shù)據(jù)
      email: "email1@qq.com",
      email1: "",
      email2: "email2@qq.com",
      email3: "email3@qq.com",
      email4: "email4@qq.com",
      email5: 123,
      //開關(guān), 決定是否是展示狀態(tài)還是編輯狀態(tài), disabled禁用屬于編輯狀態(tài)
      status: false,
      //確定每一行唯一的key
      key: new Date().getTime()
    }
  ]
}

6. 由于這個功能相對復(fù)雜, 我們還需要內(nèi)部定制一個參數(shù)用于臨時使用

a. 當(dāng)我們點(diǎn)編輯的時候要暫存這個數(shù)據(jù), 以備用戶點(diǎn)擊取消的時候恢復(fù)使用, 因?yàn)橛脩艨赡芤淮吸c(diǎn)了好幾個編輯, 我們都要存儲, 又因?yàn)槲覀冇幸粋€key值可以當(dāng)我們的索引, 我們只需要把用戶點(diǎn)擊編輯的數(shù)據(jù)push一個數(shù)組就夠了

cancelListData:[
  {
      //表格一行的數(shù)據(jù)
      email: "email1@qq.com",
      email1: "",
      email2: "email2@qq.com",
      email3: "email3@qq.com",
      email4: "email4@qq.com",
      email5: 123,
      status: false,
      //確定每一行唯一的key
      key: new Date().getTime()
    }
]

7. 好了基本需要的東西我們都準(zhǔn)備完了, 接下來還要實(shí)現(xiàn)組件里的方法

    methods:{
        addRowListJudge(){
            // 判斷是否有未操作完的行, 然后才允許新增一行, 也是為了提交表單時判斷更為簡便
        },
        handleEdit(){
            // 調(diào)用傳入的修改狀態(tài)的方法
        },
        handleCancel(){
            // 調(diào)用傳入的取消方法
        },
        handleDelete(){
            // 調(diào)用傳入的刪除行的方法
        },
    }

8. 最后一步就是實(shí)現(xiàn)各個方法就可以了, 這里就不細(xì)寫了, 具體還是直接看代碼吧, 代碼放在:https://github.com/wqliusong/happy/tree/master/rowList, 有可以直接運(yùn)行的單頁面下載就可以看, 也希望各位路過的朋友能給提點(diǎn)意見, 先謝過

總結(jié): 最后來說一下自己遇到的一些家長里短的問題

a. 第一個就是淺拷貝深拷貝的問題, 有很多人說淺拷貝深拷貝有啥用, 平時也基本遇不到, 這里就給了一個例子, 代碼中有注釋, 具體會遇到什么問題, 我在這里說一下, 當(dāng)我在從不可編輯變?yōu)榭删庉嫷臅r候我要先備份一下當(dāng)前行, 便于點(diǎn)取消的時候能夠恢復(fù), 如果我用了淺拷貝, 這個數(shù)組里的內(nèi)容指向的還是同一個地址, 當(dāng)我改變當(dāng)前行的時候, 其實(shí)我備份的那個也已經(jīng)變了, 所以就不能恢復(fù)了, 即一個動, 全都動, 所以這里要畫個重點(diǎn)

b. 第二個就是vue視圖更新的問題, 數(shù)組內(nèi)容更新, vue視圖是不會自動更新的, 具體可以查看官網(wǎng)的https://cn.vuejs.org/v2/guide/reactivity.html, 所以用splice去處理數(shù)組, 當(dāng)然還有好多辦法, splice比較簡單

c. 關(guān)于業(yè)務(wù)封裝組價的問題, 因?yàn)槊總€人的業(yè)務(wù)是不同的, 做出符合各種功能的組件是很難的, 所以各個ui庫會盡量的把功能拆分的細(xì)小一點(diǎn), 也會更加靈活, 而我們在實(shí)際業(yè)務(wù)開發(fā)中, 我們想要的是更加節(jié)省時間, 所以在原有細(xì)小的基礎(chǔ)上做一些相對功能豐富一點(diǎn), 而且更易于配置的組件, 像這個組件, 我們除了在開發(fā)中調(diào)用它, 我們甚至只要幾個空間, 在數(shù)據(jù)庫中配置這個大json就可以了, 而不用每次都要在前端配置

當(dāng)然不同的公司也會有不同的考慮, 還是希望大家都能有所進(jìn)步, 也可以把你們的想法告訴我, 帶我這個渣渣一起進(jìn)步, 再次感謝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子洛波,更是在濱河造成了極大的恐慌,老刑警劉巖骚露,帶你破解...
    沈念sama閱讀 216,843評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異缚窿,居然都是意外死亡棘幸,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,538評論 3 392
  • 文/潘曉璐 我一進(jìn)店門倦零,熙熙樓的掌柜王于貴愁眉苦臉地迎上來误续,“玉大人吨悍,你說我怎么就攤上這事√G叮” “怎么了育瓜?”我有些...
    開封第一講書人閱讀 163,187評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長栽烂。 經(jīng)常有香客問我躏仇,道長,這世上最難降的妖魔是什么腺办? 我笑而不...
    開封第一講書人閱讀 58,264評論 1 292
  • 正文 為了忘掉前任焰手,我火速辦了婚禮,結(jié)果婚禮上怀喉,老公的妹妹穿的比我還像新娘书妻。我一直安慰自己,他們只是感情好躬拢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,289評論 6 390
  • 文/花漫 我一把揭開白布躲履。 她就那樣靜靜地躺著,像睡著了一般聊闯。 火紅的嫁衣襯著肌膚如雪工猜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,231評論 1 299
  • 那天馅袁,我揣著相機(jī)與錄音域慷,去河邊找鬼。 笑死汗销,一個胖子當(dāng)著我的面吹牛犹褒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弛针,決...
    沈念sama閱讀 40,116評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼叠骑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了削茁?” 一聲冷哼從身側(cè)響起宙枷,我...
    開封第一講書人閱讀 38,945評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎茧跋,沒想到半個月后慰丛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,367評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瘾杭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,581評論 2 333
  • 正文 我和宋清朗相戀三年诅病,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,754評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡贤笆,死狀恐怖蝇棉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情芥永,我是刑警寧澤篡殷,帶...
    沈念sama閱讀 35,458評論 5 344
  • 正文 年R本政府宣布,位于F島的核電站埋涧,受9級特大地震影響板辽,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜飞袋,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,068評論 3 327
  • 文/蒙蒙 一戳气、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧巧鸭,春花似錦瓶您、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,692評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至郑叠,卻和暖如春夜赵,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背乡革。 一陣腳步聲響...
    開封第一講書人閱讀 32,842評論 1 269
  • 我被黑心中介騙來泰國打工寇僧, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沸版。 一個月前我還...
    沈念sama閱讀 47,797評論 2 369
  • 正文 我出身青樓嘁傀,卻偏偏與公主長得像,于是被迫代替她去往敵國和親视粮。 傳聞我的和親對象是個殘疾皇子细办,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,654評論 2 354