likes
comments
collection
share

实战:低代码的场景-下拉选择关联(下)

作者站长头像
站长
· 阅读数 26

前言


我知道这对你来说可能有些困难,但请相信我,你有足够的能力去克服它。

实战:低代码的场景-下拉选择关联(下)

仔细看下去,相信能收获一些干货滴~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

一、问题剖析

还没看过的,可以先移步去看看,看完在接着这篇。

实战:低代码的场景-下拉选择关联(下)

后续需求的迭代,发现挺有意思的,继续输出😘

我们先来回顾一下需求:

有一个表单,有

  • 下拉框A,选项值为A1和A2
  • 下拉框B,选项值为B1和B2
  • 下拉框C,选项值为C1和C2

现在需要做关联关系的约束,不然在填报的时候 选项太多容易搞错。

比如通过低代码配置下拉框A,选了A1之后,触发下拉框B的选项值改变

下拉框B,选了B1之后,触发下拉框C的选项值改变。

丝滑入场 😋。

二、下次编辑进入,更新option

直到我认为万无一失的时候,新增的时候,关联修改了选项。

操作:

  • A字段关联了B字段,把option(A1、A2)赋值给B
  • B字段原本的option(B1、B2)

当我下次编辑的时候,字段B的option恢复原本的(B1、B2),而我编辑的值比如A1,在字段B中找不到A1,因为option被恢复原本的值。

我们需要在编辑进入的时候,也要去改变option是关联的选项。

因为编辑的时候,options没有更新,需手动触发

  • this.fields:表单字段的配置
// 因为编辑的时候,options没有更新,需手动触发
this.fields.forEach(f =>{
  // item是当前的值,添加notUpdateVal属性:代表不更新val,因为change内部会将val赋空
    this.change({ config: f, item: this.formData[f.id], notUpdateVal: true  })
})

实战:低代码的场景-下拉选择关联(下)

三、需求迭代

以上是编辑/新建的情况下,现在需要列表的时候可以修改。

按理说���可以把上面编辑的那套逻辑搬过去。

代码如下:

change(data){
    const dataControl = getV(data, 'config', 'config', 'dataControl')
    // 关联关系,通过下拉选项选择 A,约束后面的可选择项
    if(getV(dataControl, 'length')){
        let obj  = {}
        for (let index = 0; index < dataControl.length; index++) {
            const element = dataControl[index];

            const f = this.fields.find(f => f.id == element.srcFormFieldKey && getV(f, 'slot', 'options'))
            if(f.id == element.srcFormFieldKey && getV(f, 'slot', 'options')){
                if(!getV(f, 'slot', 'options_backup', 'length')) f.slot.options_backup = JSON.parse(JSON.stringify(f.slot.options))  || [] // backup config
                
                if(data.formData && data.formData[f.id] && !data.notUpdateVal) {
					data.formData[f.id] = ``  // update val
				}
                const isEqual = (element) => Array.isArray(data.item) ? data.item.includes(element.currentVal) : element.currentVal == data.item // 当前值和配置的值--是否相等
                const opt = equals(f.slot.options, f.slot.options_backup) ? element.options : this.uniqueArray2(dataControl.filter(c => isEqual(c) ).map(m => m.options).flat())   // 判断当前的option是否和原始的一样,如果一样就直接赋值(第一次进入);否则,第二次就合并后去重
                
                f.slot.options = isEqual(element) ? opt : f.slot.options_backup; // update config
                getV(f, 'config', 'dataControl', 'length') && this.change({ config: f, notUpdateVal: data.notUpdateVal })  // 若为空,清空之前的数据
                    
                if(isEqual(element)) break;
            }
        }
        
    }
},

基本没什么变化,唯一需要注意的点是:

A字段当前的值选了A1,把A1的option赋值给B字段

然后保存😊

第二次编辑的时候,直接选择B字段,发现选项又恢复初始化了,但第一次编辑的时候,我们已经修改了A字段,把A1的option给B字段了。

可现在又初始化了。

预期:第二次编辑的时候,也要回显A1的option给B字段。

方案

我一开始的想法是:

因为编辑的时候,options没有更新,需手动触发

现在是列表,二维,需要遍历两层,拿到列,再到行

// 列
this.fields.forEach((f, fIndex) =>{
	// 行
	this.dataList.forEach(d =>{
		this.change({ config: f, item: d[f.id], notUpdateVal: true  })
	})
})

可是,你忘记了一个点:

我们的整个表格的行,对应的都是一个列的配置。

上面的循环,数据再怎么循环,都是操作一个列的对象,不能想A数据的【名字--列】显示A1;

B数据的【名字--列】显示B1;

按照上面的写法,都是一样的。

实战:低代码的场景-下拉选择关联(下)

所以,不可行 🤡。

不像我们的新建/编辑,只是操作一条数据,这里列表操作的是多条数据。

方案二

我们现在改变select的选项会去找他的下游,改变下游(孩子)的选项。

那我们是不是点击select的时候可以去寻找他的上游(父亲)

注意,这是两个事件:

  • click点击:寻找上游
  • change改变值:寻找下游

现在,我们来看看click事件是怎么寻找上游的。

template

可以看到我们的click事件,添加了native因为他是组件。

<item :conf="item" :row="scope.row" 
  @click.native="clickEdit({config: item, formData: scope.row})" 
  @change="(e) => change({item: e, config: item, formData: scope.row})" />

我们重点来看看clickEdit函数

  • 遍历表格的配置,找到当前配置的上游(父亲)
  • 我们dataControl配置的是数组,命中当前值才会选择option
  • 寻找父亲当前命中的值
  • 拿到之后去设置给孩子

总结:当前的数据的配置,去寻找他关联的父亲,找到父亲的选项,赋值给孩子。

clickEdit(data){
	// this.fields:整个表格的配置
	const fater_find = this.fields.find(f => {
		const dataControl = getV(f, 'config', 'dataControl') // 关联的属性
		if(getV(dataControl, 'length')){
             // 找到父亲
			return dataControl.find(d => d.srcFormFieldKey == data.config.id )
		}
	})
	if(getV(fater_find, 'config', 'dataControl', 'length')){
        // data.formData:数据
        // 我们dataControl配置的是数组,命中当前值才会选择option
        // 寻找父亲当前命中的值
		const dataControl_find = fater_find.config.dataControl.find(f => f.currentVal == data.formData[fater_find.id])
		if(getV(dataControl_find, 'options', 'length')){
             // 拿到之后去设置给孩子
			data.config.__slot__.options = dataControl_find.options
		}
	}
},

其实这些公共的方法,在我的github上有写过:ArrayTool

后记

这种类似的场景一般用于可视化低代码平台中。

会根据配置来动态渲染。

做好扩展性,遵守开闭原则。

当然,我们还要考虑安全性防XSS注入,防止外部嵌入,导致安全问题。

如果有其他更好的方法也欢迎评论区见,这里提供的只是诸多方法之一。

最后,祝君能拿下满意的offer。

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

原文链接

转载自:https://juejin.cn/post/7397022072058691594
评论
请登录