最近,花了一周时间用宜搭做了个Web工具。中间遇到很多坑,还好宜搭的文档不错,除了基本的功能使用开发介绍外,还有很多专题案例,基本上可以找到答案,或从中得到灵感。选用宜搭的原因,除了团队最近在使用,主要还是因为它是低代码,可迅速搭建界面,开发语言是js,非常容易上手。
1 必备
先把个人觉得非常重要的文档和常用快捷键,放上来:
1.1 文档
1.2 快捷键
在写js代码时,肯定要快捷键,好像跟vscode的快捷键一样。这几个是我经常使用的
快捷键 | 说明 |
---|---|
复制行到上或下 | ⇧ + ⌥ + ↑[或↓] |
向上或下移动当前行 | ⌥ + ↑[或↓] |
多行选择 | ⇧ + ⌥ + 光标选择 |
删除行 | ⇧ + ⌘ + K |
向后搜索并添加到选择中(批量修改) | ⌘ + D |
2 下拉单选
表单和自定义页面,都有下拉单选组件,表单中叫“下拉单选”,自定义页面叫“下拉选择”,两者功能都一样,只是在不同页面中的不同叫法而已。
下面由表入里,讲述它的使用
2.1 设置显示状态
// NORMAL:正常显示,DISABLED:禁用,READONLY:只读,HIDDEN:隐藏
this.$("selectField_kvnwz0n2").setBehavior("READONLY")
// 或
this.$("selectField_kvnwz0n2").set("behavior", "READONLY")
2.2 设置占位符placeholder
this.$("selectField_kvnwz0n2").set("placeholder", "请选择地区")
2.3 设置下拉选项
this.$("selectField_kvnwz0n2").set("dataSource", [{
text: '中国',
value: '中国'
},
{
text: '日本',
value: '日本'
},
{
text: '韩国',
value: '韩国'
}
])
text对应的是显示值;value是组件值,即this.$("selectField_kvnwz0n2").getValue()
tips:如果还想保存其它信息,比如首都,都可以往里塞。可以通过动作export function onChange({value, actionType, item})的item获取
2.4 获取下拉选项
this.$("selectField_kvnwz0n2").cachedDataSource
// 或
this.$("selectField_kvnwz0n2").getProps().dataSource
2.5 设置值
this.$("selectField_kvnwz0n2").setValue("中国")
2.6 获取值
this.$("selectField_kvnwz0n2").getValue()
2.7 子表单中的下拉单选
先看下我们要实现的效果:
子表单中的首都项和城市项,默认READONLY。当选择国家后,首都自动填入;城市根据所选国家,一把占位提示改成“选择{国家}城市”,然后把该国的部分城市更新到下拉选项中供选择
很多时候,我们需要处理子表单中的下拉单选。有些功能通过上述方式无法实现。来,上菜:
- 状态和组件值,还是可以通过原方式setBehavior()和setValue()来设置
- placeholder和dataSource,得通过来setComponentProps()来设置了
说明:
set("placeholder", yourPlaceHolder)
和set("dataSource", yourOptions)
,有时也可以在动作(如:onChange)中使用,但第一表单的第一行里设置无效。实在要用,可以在页面最前面加个隐藏、不提交数据的子表单也行。但为了安全起见,不推荐使用
2.7.1 状态和值
/**
* 当子菜单的国家选择之后执行
*/
export function onSubNationChange({value, actionType, item}) {
console.log('onSubNationChange', value);
const cityField = this.$(sub_single_city_id)
cityField.setValue("")
if(typeof value == "undefined"){
cityField.setBehavior("READONLY")
return
}
cityField.setBehavior("NORAML")
}
在子菜单同一行的动作中,如onChange(),可以直接通过this.$()
来获取本行中的其它组件。正如上述代码所示,可以直接获取本行的城市组件。如果在其他位置,获取的就是一个组件数组了
setValue()
其实有个坑,往下看
2.7.2 占位符和下拉选项
先了解下这个方法,它是用来设置子表单中某个组件的属性
tableField.setComponentProps(groupId, fieldId, data)
- groupId:条目id,也就是所在行的id,eg:tfitem_3。通过
tableField.getItems()
可获取所有条目id - fieldId: 组件id
- data:属性值
export function onSubNationChange({value, actionType, item}) {
console.log('onSubNationChange', value);
const cityField = this.$(sub_single_city_id)
cityField.setValue("")
if(typeof value == "undefined"){
cityField.setBehavior("READONLY")
return
}
cityField.setBehavior("NORAML")
// 获取当前item的groupId
const groupId = this.$(sub_single_nation_id).formGroupId
table_field.setComponentProps(groupId, sub_single_city_id, {
placeholder: "选择" + value + "城市",
dataSource: item.cities.map(it => {
return {
text: it,
value: it
}
})
})
}
上述代码中,如果直接通过组件设置,那第一个表单的第一行将无效。可以试试看,后半部分的代码改成如下:
cityField.setBehavior("NORAML")
// 直接通过组件设置(不推荐)
cityField.set("placeholder", "选择" + value + "城市")
cityField.set("dataSource", item.cities.map(it => {
return {
text: it,
value: it
}
})
)
2.7.3 setValue()无效?
现在,我们在onChange()中不直接设置,而是先通过从其它表单中查找数据,再设置:
export function onSubNationChange({value, actionType, item}) {
...省略...
// 首都
const capitalField = this.$(sub_single_capital_id)
// capitalField.setValue(item.capital)
const params = {
formUuid: "FORM-2O86******01",
searchFieldJson: JSON.stringify({
textField_kvp2qxo7: value
})
}
this.dataSourceMap['searchFormDatas'].load(params).then(resp => {
console.log("searchCaptical=" + JSON.stringify(resp))
let capital
if (resp.data.length > 0) {
capital = resp.data[0].formData.textField_kvp2qxo8
}
console.log("arr", capital)
// capitalField.setValue(capital)
const groupId = this.$(sub_single_nation_id).formGroupId
table_field.setComponentProps(groupId, sub_single_capital_id, {value: capital})
})
...省略...
}
我们把首都设置为必填。在提交表单时,发现报错了:
明明已经设置进去了,都显示了,怎么还报错了?如果不设置必填,查看数据时会发现,此项为空。除非手动填入
尝试过table_field.setComponentProps(groupId, sub_single_capital_id, {value: capital}),也不行
向上找思路,就是通过子表单来完成,子表单有setValue(),我们通过这个方法来迂回解决。但要注意子表单还要其它数据,所以只能更新首都项的数据。这样更新,虽然数据正确了,但不会显示,所以还得加上capitalField.setValue(capital)
this.dataSourceMap['searchFormDatas'].load(params).then(resp => {
console.log("searchCaptical=" + JSON.stringify(resp))
let capital
if (resp.data.length > 0) {
capital = resp.data[0].formData.textField_kvp2qxo8
}
console.log("capital", capital)
const tbVal = table_field.getValue()
console.log("table old value", tbVal)
tbVal[itemIndex].selectField_kvnwz0n8 = capital
table_field.setValue(tbVal)
capitalField.setValue(capital)
})
其中,子表单的数据格式如下:
要是有更好的方法,麻烦告知,感谢!
3 附录
3.1 数据源
![数据源](https://i-blog.csdnimg.cn/blog_migrate/030b0033be64b5f999cfa370aaa88633.jpeg#pic_center)
/**
* 下拉单选_表单案例
* @author Ralap
* @date 2021-11-07
*/
const countries = [{
text: '中国',
value: '中国',
capital: '北京',
cities: [
"北京",
"上海",
"杭州",
"广州",
"深圳"
]
},
{
text: '日本',
value: '日本',
capital: '东京',
cities: [
"东京",
"大阪",
"横滨",
"名古屋"
]
},
{
text: '韩国',
value: '韩国',
capital: '首尔',
cities: [
"首尔",
"釜山",
"济州"
]
}
]
let outer_single_field
let outer_text_field
let table_field
const sub_single_nation_id = 'selectField_kvnwz0n5'
const sub_single_city_id = 'selectField_kvnwz0n6'
const sub_single_capital_id = 'selectField_kvnwz0n8'
export function didMount() {
console.log(`「页面 JS」:当前页面地址 ${location.href}`)
this.initFields()
}
export function initFields() {
outer_single_field = this.$("selectField_kvnwz0n2")
outer_text_field = this.$("textField_kvnwz0n3")
table_field = this.$("tableField_kvnwz0n4")
outer_single_field.set("placeholder", "请选择国家")
outer_single_field.set("dataSource", countries)
// 初始化子表单的第一行
const latestIndex = table_field.getItems().length - 1
const groupName = table_field.getItems()[latestIndex]
table_field.setComponentProps(groupName, sub_single_nation_id, {
placeholder: "请选择国家_sub",
dataSource: countries
})
// 第一行也可以通过这样来赋值
// this.$(sub_single_nation_id)[0].set("placeholder", "请选择国家_sub")
// this.$(sub_single_nation_id)[0].set("dataSource", countries)
}
export function onOuterNationChange({ value, actionType, item }) {
console.log('onOuterNationChange: value', value);
console.log('onOuterNationChange: actionType', actionType);
console.log('onOuterNationChange: item', item);
console.log("dataSource1:", outer_single_field.getProps().dataSource)
console.log("dataSource2:", outer_single_field.cachedDataSource)
outer_text_field.setValue(item.capital)
}
/**
* 当子菜单的国家选择之后执行
*/
export function onSubNationChange({value, actionType, item}) {
console.log('onSubNationChange', value);
const cityField = this.$(sub_single_city_id)
cityField.setValue("")
if(typeof value == "undefined"){
cityField.setBehavior("READONLY")
return
}
cityField.setBehavior("NORAML")
// 首都
const capitalField = this.$(sub_single_capital_id)
// capitalField.setValue(item.capital)
const itemIndex = table_field.getItems().indexOf(capitalField.formGroupId)
const params = {
formUuid: "FORM-2O86******01",
searchFieldJson: JSON.stringify({
textField_kvp2qxo7: value
})
}
this.dataSourceMap['searchFormDatas'].load(params).then(resp => {
console.log("searchCaptical=" + JSON.stringify(resp))
let capital
if (resp.data.length > 0) {
capital = resp.data[0].formData.textField_kvp2qxo8
}
console.log("capital", capital)
const tbVal = table_field.getValue()
console.log("table old value", tbVal)
tbVal[itemIndex].selectField_kvnwz0n8 = capital
table_field.setValue(tbVal)
// 加上,才能显示
capitalField.setValue(capital)
})
// 获取当前item的groupId
const groupId = this.$(sub_single_nation_id).formGroupId
table_field.setComponentProps(groupId, sub_single_city_id, {
placeholder: "选择" + value + "城市",
dataSource: item.cities.map(it => {
return {
text: it,
value: it
}
})
})
// set()方式设置,有缺陷
// cityField.set("placeholder", "选择" + value + "城市")
// cityField.set("dataSource", item.cities.map(it => {
// return {
// text: it,
// value: it
// }
// })
// )
}
/**
* TableField onAddClick
*/
export function onSubAddClick(newGroupId){
console.log('onSubAddClick');
// 子表单添加一项后,对其初始化。
// 这里还不能通过this.$(sub_single_nation_id)找到
const latestIndex = table_field.getItems().length - 1
const groupName = table_field.getItems()[latestIndex]
table_field.setComponentProps(groupName, sub_single_nation_id, {
placeholder: "请选择国家_sub",
dataSource: countries
})
}