vue2 中如何實(shí)現(xiàn)動(dòng)態(tài)表單增刪改查

最近項(xiàng)目中遇到的需求是要操作大量的表單,之前的項(xiàng)目中有做過這方的研究述召,只不過是用jquery來操作俘枫。

項(xiàng)目A

先簡(jiǎn)單說說以前項(xiàng)目A中的應(yīng)用場(chǎng)景,可能有小伙伴兒也遇到相同的需求萧恕。A項(xiàng)目是公司的OA系統(tǒng)中有的項(xiàng)目刚梭,是用java的jsp渲染的頁(yè)面,需求是要改成:嵌入APP中顯示票唆,前后端分離朴读, 后端返回的內(nèi)容,還不能修改走趋, 只是后端同事做了下接口處理衅金,返回給前端的是一大堆的表單數(shù)據(jù)。

每個(gè)表單都有多個(gè)字段表示它的屬性:

  • 是否可編輯
  • 表單類型 (text, textarea, select, radio, checkbox, hidden等 )
  • 與之聯(lián)動(dòng)的其他表單
  • 簿煌。氮唯。。
    之前的方案就是各個(gè)表單類型和字段屬性進(jìn)行判斷姨伟,調(diào)用不同的UI組件(如時(shí)間日歷選擇器等)

項(xiàng)目B

現(xiàn)在遇到的項(xiàng)目惩琉,展示類型少很多,第一個(gè)想到的就是同樣的方法授滓,不過這次使用的是Vue的雙向綁定琳水。

以下是我在python后端項(xiàng)目中的經(jīng)驗(yàn),如果沒有興趣可以直接看最后的動(dòng)態(tài)表單部分

1 python 后端項(xiàng)目中如何引入Vue

項(xiàng)目B用的是python的jinjia2的模板般堆, 同樣都是 {{}} 去解析數(shù)據(jù),這種情況下怎么辦呢诚啃?

{% raw %}
<script type="text/x-template" id="dialog-wrap">
<div class="ms-dialog-wrap" v-show="visible">
  <div class="ms-dialog-inner">
    <div class="ms-dialog-title">{{title}}</div>
    <div class="ms-dialog-body">
      <div class="ms-dialog-content">
        <slot></slot>
      </div>
      <div class="ms-dialog-actions">
        <a class="ms-button" @click="cancelAction">取消</a>
        <a class="ms-button ms-success" @click="confirmSuccess">確定</a>
      </div>
    </div>
  </div>
  <div class="ms-overlayer" @click="cancelAction"></div>
</div>
</script>
{% endraw %}

jinjia2中使用 raw 可以阻止解析內(nèi)部的代碼淮摔,這樣就可以引入我們的vue模板了,這里是我寫的一個(gè)dialog彈框的組件
2 定義組件
這里以dialog彈窗組件為例子始赎,直接上代碼

// dialog彈框
Vue.component('ms-dialog', {
  name: 'ms-dialog',
  template: '#dialog-wrap',
  data: function () {
    return {
    }
  },
  props: {
    title: String,
    value: {
      type: Boolean,
      required: false
    }
  },
  computed: {
    visible: function () {
      return this.value
    }
  },
  watch: {
    visible: function (newVal) {
      if (newVal) {
        document.addEventListener('wheel', this.disabledScroll, false)
      } else {
        document.removeEventListener('wheel', this.disabledScroll, false)
      }
    }
  },
  methods: {
    confirmSuccess: function () {
      this.$emit('confirm-success')
    },
    cancelAction: function () {
      this.$emit('input', false)
    },
    disabledScroll: function (e) {
      e.preventDefault()
    }
  },
  beforeDestroy: function () {
    document.removeEventListener('scroll', this.disabledScroll, false)
  }
})

動(dòng)態(tài)表單組件

一般的需求是:

  • 一個(gè)列表和橙,可以實(shí)現(xiàn)列表的動(dòng)態(tài)添加,刪除造垛。
  • 列表中的每一項(xiàng)是動(dòng)態(tài)的表單魔招,表單個(gè)數(shù)不確定,
  • 有提交功能五辽,提交或者可以保存整個(gè)表單
  • 保存的表單办斑,通過接口調(diào)回后,回填表單杆逗,還可以再次修改乡翅、增加、刪除等
1 如何生成動(dòng)態(tài)表單
<template v-for="item in lists">
      <div class="list-item" v-if="list.type === 'input'">
        <label>用戶名</label>
        <input type="text" v-model="item.value" :value="list.defaultValue" class="form-control">
      </div>
      <div class="list-item" v-if="list.type === 'input'">
        <label>密碼</label>
        <input type="text" v-model="item.value" :value="list.defaultValue" class="form-control">
      </div>
      <div class="list-item" v-if="list.type === 'textarea'">
        <label>說明</label>
        <textarea rows="3" v-model="item.value" :value="list.defaultValue" class="form-control"></textarea>
      </div>
      <div class="list-item" v-if="list.type === 'select'">
        <label>性別</label>
        <select v-model="list.value" :value="list.defaultValue">
            <option v-for="sub in list.source" :value="sub.value">{{sub.label}}</option>
        </select>
      </div>
</template>

我們的與后端商量好的數(shù)據(jù)格式可以是這樣的罪郊;

lists:  [{
  type: 'input',
  defaultValue: 'tom',
  value: 'tom'
}, {
  type: 'input',
  defaultValue: '123456',
  value: '123456'
}, {
  type: 'textarea',
  defaultValue: '123456',
  value: '123456'
}, {
  type: 'select',
  defaultValue: '0',
  value: '0',
  source: [{
    value: '1',
    label: '男'
  }蠕蚜, {
    value: '1,
    label: '女'
  }]
}]

這樣一個(gè)動(dòng)態(tài)模板就生成了,其他更多類型都可以定義悔橄。這份模板數(shù)據(jù)靶累,一般是需要緩存的腺毫。因?yàn)榻酉聛淼?添加操作也需要這份數(shù)據(jù)。

添加操作

上面的template只是其中一個(gè)動(dòng)態(tài)列表挣柬。

<div v-for="book in books">
    <template v-for="item in book.lists">
      ......
    </template>
</div>
<div class="actions">
<button @click="add"></button>
</div>

add的方法一般是:

methods: {
 add:  function () {
   this.books.push({
    lists:  [{
      type: 'input',
      defaultValue: 'tom',
      value: 'tom'
    }, {
      type: 'input',
      defaultValue: '123456',
      value: '123456'
    }, {
      type: 'textarea',
      defaultValue: '123456',
      value: '123456'
    }, {
      type: 'select',
      defaultValue: '0',
      value: '0',
      source: [{
        value: '1',
        label: '男'
      }潮酒, {
        value: '1,
        label: '女'
      }]
    }]
 })
 },

這里需要注意的是,如果這份模板的數(shù)據(jù)凛忿,你是通過在data屬性中定義的字段去緩存的澈灼,那有可能遇到的是你通過添加操作之后的表單的值會(huì),會(huì)隨著其中的某個(gè)表單的值一起聯(lián)動(dòng)店溢。
具體原因叁熔,猜測(cè)是這里的數(shù)據(jù)已經(jīng)是變成響應(yīng)式的了, 又或者你 通過實(shí)例化后的值去緩存這份模板數(shù)據(jù)床牧,可能結(jié)果還是這樣荣回。
具體代碼可能是這樣的:

var vm = new Vue({
    data: {
        books: [],
        cacheTemplate: null
    },
    methods: {
        getForms: function (argument) {
            this.$http.post(url, paras).then(res => {
                // 此處緩存了這份模板數(shù)據(jù),cacheTemplate中的數(shù)據(jù)已經(jīng)變成響應(yīng)式的了, 此處cacheTemplate是引用類型
                this.cacheTemplate = res.body.data
                this.books.push(res.body.data) // 創(chuàng)建第一動(dòng)態(tài)表單列表
            }, res => {

            })
        },
        add: function () {
            // 因?yàn)槭且妙愋透昕龋詂acheTemplate屬性值的變化必然影響其他和它相同屬性的值
                     this.books.push(this.cacheTemplate)
        }
    }
})

此處的解決方法: 是要換成深度復(fù)制心软。
直接上代碼:

var vm = new Vue({
    data: {
        books: [],
        cacheTemplate: null
    },
    methods: {
        getForms: function (argument) {
            this.$http.post(url, paras).then(res => {

                // 此處同樣緩存了這份模板數(shù)據(jù),不同的是把它變成了字符串, 深度復(fù)制
                this.cacheTemplate = JOSN.stringify(res.body)
                this.books.push(res.body) // 創(chuàng)建第一動(dòng)態(tài)表單列表
            }, res => {

            })
        },
        add: function () {
            // 此處轉(zhuǎn)化成json對(duì)象
            var cacheTemplate = JSON.parse(this.cacheTemplate)
            this.books.push(cacheTemplate)
        }
    }
})

如果覺得本文不錯(cuò)的話著蛙,歡迎點(diǎn)贊删铃。如有問題, 大家一起交流和學(xué)習(xí)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末踏堡,一起剝皮案震驚了整個(gè)濱河市猎唁,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌顷蟆,老刑警劉巖诫隅,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異帐偎,居然都是意外死亡逐纬,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門削樊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來豁生,“玉大人,你說我怎么就攤上這事嫉父∨婀瑁” “怎么了?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵绕辖,是天一觀的道長(zhǎng)摇肌。 經(jīng)常有香客問我,道長(zhǎng)仪际,這世上最難降的妖魔是什么围小? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任昵骤,我火速辦了婚禮,結(jié)果婚禮上肯适,老公的妹妹穿的比我還像新娘变秦。我一直安慰自己,他們只是感情好框舔,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布蹦玫。 她就那樣靜靜地躺著,像睡著了一般刘绣。 火紅的嫁衣襯著肌膚如雪樱溉。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天纬凤,我揣著相機(jī)與錄音福贞,去河邊找鬼。 笑死停士,一個(gè)胖子當(dāng)著我的面吹牛挖帘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播恋技,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼拇舀,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼摊欠!你這毒婦竟也來了憔辫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤醒颖,失蹤者是張志新(化名)和其女友劉穎朱躺,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體搁痛,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡长搀,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鸡典。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片源请。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖彻况,靈堂內(nèi)的尸體忽然破棺而出谁尸,到底是詐尸還是另有隱情,我是刑警寧澤纽甘,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布良蛮,位于F島的核電站,受9級(jí)特大地震影響悍赢,放射性物質(zhì)發(fā)生泄漏决瞳。R本人自食惡果不足惜货徙,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望皮胡。 院中可真熱鬧痴颊,春花似錦、人聲如沸屡贺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)甩栈。三九已至泻仙,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間谤职,已是汗流浹背饰豺。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留允蜈,地道東北人冤吨。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像饶套,于是被迫代替她去往敵國(guó)和親漩蟆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容