聯動規則的構建(個人構建方式):
構思:
整個form表單分爲2個部分
1是form 主要是整個form的顯示,提交取消回調,錯誤信息顯示等
2輸入控件:如select等vue
如今添加聯動規則,select爲例:
select的選項獲取有2種,參數設定和ajax獲取兩種
因此聯動有兩種形式:過濾現有的選項和重置ajax請求參數獲取選項
1.設置要聯動的字段參數
過濾:ios
{ type: 'select', name: 'column2', column: '', linkage: 'column1', // 與form字段column1聯動 linkageFilter (item, val) { return item.value == val }, options: [ {text: '測試1', value: '1'}, {text: '測試2', value: '2'}, {text: '測試3', value: '3'} ] }
ajax參數:ajax
{ type: 'select', name: 'column2', column: '', linkage: 'column1', // 與form字段column1聯動 url: '/' // 只須要參數就好,到時select組件會自動將 column1='val' 做爲請求參數 }
2.form.vue watch監聽選項變化
檢查每一個字段是否有聯動,若是有聯動,將變化的值賦予對應的select組件內的linkageValaxios
form: { handler (val) { // 聯動規則 for(var i in this.options.columns){ if (this.options.columns[i].linkage){ this.$refs[this.options.columns[i].column][0].linkageVal = val[this.options.columns[i].linkage] } } }, deep: true }
3.select.vue 監聽linkageVal的變化
分別根據是否有url參數執行過濾仍是從新ajax請求測試
個人源碼:
form.vue組件ui
<template> <form v-if="options" onsubmit="return false"> <template v-for="c in options.columns"> <div class="form-group"> <label> <span style="color:red" v-if="c.required">*</span> {{ c.name }} </label> <component :is="'v-'+c.type" :class="!errors[c.column]?'form-control':'form-control is-invalid'" :options="c" v-model="form[c.column]" :ref="c.column"/> <div class="invalid-feedback" v-if="errors[c.column]">{{ errors[c.column] }}</div> </div> </template> <a class="btn border" v-on:click="onCancel">取消</a> <div class="form-group" v-if="!options.template"> <div class="col-sm-12 justify-between text-right"> <a class="btn border" v-on:click="onCancel">取消</a> <button class="btn btn-primary" v-on:click="onSave"> <i class="fa fa-spin fa-circle-o-notch" v-if="options.submiting"/> 保存 </button> </div> </div> </form> </template> <script> import select from './control/select' export default{ name: 'components-common-content-form', props: ['options'], data () { return { form: {}, errors: {} } }, watch: { errors () { this.$forceUpdate() }, form: { handler (val,oVal) { if (typeof this.options.watch == 'function') { this.options.watch(val) } // 聯動規則 for(var i in this.options.columns){ if (this.options.columns[i].linkage){ this.$refs[this.options.columns[i].column][0].linkageVal = val[this.options.columns[i].linkage] } } }, deep: true } }, methods: { onSave () { if (typeof this.options.onSave == 'function') { this.options.onSave(this.form) } }, onCancel () { if (typeof this.options.onCancel == 'function') { this.options.onCancel(this.form) } this.$refs.ldm.getOptions() }, setData (data) { this.form = data }, clearData () { this.form = {} }, setErrors (errors) { this.errors = errors }, clearErrors () { this.errors = {} } }, components: { 'v-select': select } } </script>
select.vue 組件this
<template> <div v-if="options" class="form-control"> <div class="bg-white rounded p-2" v-if="axiosSource"> <span ><i class="fa fa-spinner fa-pulse"/> 數據加載中</span> </div> <div class="bg-white rounded" v-else> <select class="form-control" v-model="localValue"> <option value="">請選擇{{ options.name }}</option> <option v-for="o in showOptions" :value="o.value">{{ o.text }}</option> </select> </div> </div> </template> <script> export default{ name: 'components-common-content-control-checkbox', props: ['options','value'], data () { return { localValue: '', localOptions: [], linkageVal: '', axiosSource: null } }, created () { if (this.options.url) { this.getOptions() }else{ this.options.options?this.localOptions = this.options.options: this.localOptions = [] } }, watch:{ localValue () { this.$emit('input', this.localValue) }, value () { this.localValue = this.value }, // 聯動ajax請求 linkageVal () { if (this.options.url) { this.getOptions() } } }, computed: { showOptions () { var _this = this var val = _this.linkageVal var options = _this.localOptions // 聯動選項篩選 if (!this.options.url && typeof this.options.linkageFilter == 'function') { options = options.filter(function(item){ if (val){ return _this.options.linkageFilter(item, val) }else{ return true } }) } return options } }, methods: { getOptions () { var _this = this if (_this.axiosSource) { _this.axiosSource.cancel('中斷並開始新的請求'); } _this.axiosSource = axios.CancelToken.source() // 聯動請求 var url = _this.options.url if (_this.linkageVal) { url = _this.options.url + '?' + this.options.linkage + '=' + _this.linkageVal } // axios開始請求 axios.get(url) .then(function (response) { _this.localOptions = response.data _this.axiosSource = null }) .catch(function (error) { if (error.response.status == 400) { _this.alert({ title: '提示', msg: error.response.data.message }); }else{ _this.alert({ title: error.response.status + '錯誤', msg: error.response.data.message }); } _this.axiosSource = null }); } } } </script> <style scoped> .form-control{ padding: 0; height: auto; background: none; } .form-control .form-control{ border: 0px; padding: 0.375rem 0.75rem; } .form-control select{ width: 100%; height: 100%; } </style>
使用方式url
<v-form :options="options" class="w-100" ref="form"/> options: { columns: [ { type: 'select', name: 'select聯動主體', column: 'ldm', options: [ { text: '選擇1', value: 1 }, { text: '選擇2', value: 2 } ] }, { type: 'select', name: 'select聯動附體1', column: 'lda1', linkage: 'ldm', linkageFilter (item, val) { return item.value == val }, options: [ { text: '聯動1', value: 1 }, { text: '聯動2', value: 2 } ] }, { type: 'select', name: 'select聯動附體2', column: 'lda2', linkage: 'ldm', url: '/' } ] }