联动规则的构建(我的构建方式):
构思:
整个form表单分为2个部分
1是form 主要是整个form的显示,提交取消回调,错误信息显示等
2输入控件:如select等
现在添加联动规则,select为例:
select的选项获取有2种,参数设定和ajax获取两种
所以联动有两种形式:过滤现有的选项和重置ajax请求参数获取选项
1.设置要联动的字段参数
过滤:
{
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参数:
{
type: 'select',
name: 'column2',
column: '',
linkage: 'column1', // 与form字段column1联动
url: '/' // 只需要参数就好,到时select组件会自动将 column1='val' 作为请求参数
}
2.form.vue watch监听选项变化
检查每个字段是否有联动,如果有联动,将变化的值赋予对应的select组件内的linkageVal
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组件
<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 组件
<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>
使用方式
<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: '/'
}
]
}