vue快速構建form表單:聯動規則

聯動規則的構建(個人構建方式):
構思:
整個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: '/'
                    }
                ]
            }
相關文章
相關標籤/搜索