vue2 中如何實(shí)現(xiàn)動(dòng)態(tài)表單增刪改查實(shí)例
最近項(xiàng)目中遇到的需求是要操作大量的表單,之前的項(xiàng)目中有做過(guò)這方的研究,只不過(guò)是用jquery來(lái)操作。
項(xiàng)目A
先簡(jiǎn)單說(shuō)說(shuō)以前項(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è)想到的就是同樣的方法,不過(guò)這次使用的是Vue的雙向綁定。
以下是我在python后端項(xiàng)目中的經(jīng)驗(yàn),如果沒(méi)有興趣可以直接看最后的動(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模板了,這里是我寫(xiě)的一個(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è)表單
- 保存的表單,通過(guò)接口調(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>說(shuō)明</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)榻酉聛?lái)的 添加操作也需要這份數(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ù),你是通過(guò)在data屬性中定義的字段去緩存的,那有可能遇到的是你通過(guò)添加操作之后的表單的值會(huì),會(huì)隨著其中的某個(gè)表單的值一起聯(lián)動(dòng)。
具體原因,猜測(cè)是這里的數(shù)據(jù)已經(jīng)是變成響應(yīng)式的了, 又或者你 通過(guò)實(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)式的了
this.cacheTemplate = res.body.data
this.books.push(res.body.data) // 創(chuàng)建第一動(dòng)態(tài)表單列表
// 或者你是這是定義的的, 此時(shí)data中沒(méi)有cacheTemplate這個(gè)值,
// 這樣定義按理說(shuō)是非響應(yīng)式的,但實(shí)際情況并非如此,在項(xiàng)目中發(fā)現(xiàn)它還是會(huì)影響其他表單
vm.cacheTemplate = res.body.data
this.books.push(res.body.data) // 創(chuàng)建第一動(dòng)態(tài)表單列表
}, res => {
})
},
add: function () {
// 此處你會(huì)發(fā)現(xiàn)你新創(chuàng)建的表單的值會(huì)影響其他表單
// log出來(lái)this.cacheTemplate你會(huì)發(fā)現(xiàn)里面的值已經(jīng)發(fā)生了變換
this.books.push(this.cacheTemplate)
}
}
})
這里this.cacheTemplate的值為什么會(huì)發(fā)生變換,沒(méi)有搞明白, 猜測(cè)原因可能是變成響應(yīng)式了,vue中會(huì)實(shí)時(shí)監(jiān)控跟蹤,對(duì)vue原理理解好的小伙伴可以評(píng)論告訴我原因。
下面說(shuō)下我的解決方法: 我不管你是不是響應(yīng)式的,因?yàn)槭菍?duì)象,你才能監(jiān)控到變換,那我把你變成字符串不就好了。
直接上代碼:
var vm = new Vue({
data: {
books: [],
cacheTemplate: null
},
methods: {
getForms: function (argument) {
this.$http.post(url, paras).then(res => {
// 此處同樣緩存了這份模板數(shù)據(jù),不同的是把它變成了字符串
this.cacheTemplate = JOSN.stringify(res.body)
this.books.push(res.body) // 創(chuàng)建第一動(dòng)態(tài)表單列表
}, res => {
})
},
add: function () {
// 此處轉(zhuǎn)化成json對(duì)象,你發(fā)現(xiàn)this.cacheTemplate中的值是沒(méi)有變換的。
var cacheTemplate = JSON.parse(this.cacheTemplate)
this.books.push(cacheTemplate)
}
}
})
這樣其他表單值變換的時(shí)候都不會(huì)影響到我這份模板的數(shù)據(jù),問(wèn)題解決了。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
vue-cli項(xiàng)目使用vue-picture-preview圖片預(yù)覽組件方式
這篇文章主要介紹了vue-cli項(xiàng)目使用vue-picture-preview圖片預(yù)覽組件方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09
vue實(shí)現(xiàn)網(wǎng)易云音樂(lè)純界面
這篇文章主要為大家介紹了vue實(shí)現(xiàn)網(wǎng)易云音樂(lè)純界面過(guò)程詳解,附含詳細(xì)源碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07
Vue3實(shí)現(xiàn)自定義指令攔截點(diǎn)擊事件的示例代碼
某些應(yīng)用場(chǎng)景會(huì)給點(diǎn)擊事件添加權(quán)限,不存在權(quán)限就攔截點(diǎn)擊事件,有權(quán)限就繼續(xù)正常觸發(fā)點(diǎn)擊事件。這樣的效果是如何實(shí)現(xiàn)的呢,本文就來(lái)和大家詳細(xì)講講2023-02-02
使用vue制作探探滑動(dòng)堆疊組件的實(shí)例代碼
探探的堆疊滑動(dòng)組件起到了關(guān)鍵的作用,下面就來(lái)看看如何用vue寫(xiě)一個(gè)探探的堆疊組件,感興趣的朋友一起看看吧2018-03-03
Vue的子組件props如何設(shè)置多個(gè)校驗(yàn)類型
這篇文章主要介紹了Vue的子組件props如何設(shè)置多個(gè)校驗(yàn)類型問(wèn)題。具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
vue-quill-editor+plupload富文本編輯器實(shí)例詳解
這篇文章主要介紹了vue-quill-editor+plupload富文本編輯器實(shí)例詳解,需要的朋友可以參考下2018-10-10
使用VUE和webrtc-streamer實(shí)現(xiàn)實(shí)時(shí)視頻播放(監(jiān)控設(shè)備-rtsp)
WebRTC-streamer是一項(xiàng)使用簡(jiǎn)單機(jī)制通過(guò)WebRTC流式傳輸視頻捕獲設(shè)備和RTSP源的實(shí)驗(yàn),下面這篇文章主要給大家介紹了關(guān)于如何使用VUE和webrtc-streamer實(shí)現(xiàn)實(shí)時(shí)視頻播放(監(jiān)控設(shè)備-rtsp)的相關(guān)資料,需要的朋友可以參考下2022-11-11
vue中使用swiper,左右箭頭點(diǎn)擊沒(méi)有效果問(wèn)題及解決
這篇文章主要介紹了vue中使用swiper,左右箭頭點(diǎn)擊沒(méi)有效果問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05

