最近接到一个需求,大概是这样的:
某一个页面,上面是查询项,下面是列表。查询项中有两个下拉选择框,都是查询条件。这两个选择框是父子级的关系。当我选中第一个选择框某一项时,第二个选择框的下拉项会发生变化;当选择第二个选择框的某一项时,需要回填第一个选择框的值。
大概是这么个效果,这么描述起来有点复杂。下面我们来看一个实际案例,这样就会清晰很多。
假设现在有两个下拉选择框,选择框1代表公司,选择框 2 代表产品。如下图所示:
实现的功能要求如下:
通过这个案例描述,加上配图,是不是就清晰许多了。下面我们来一起实现这样的功能吧。
首先我们写一个页面布局,可以手写,也可以借助腾讯云 AI 代码助手来生成。
这里我以 element ui 为例子,用 AI 助手来生成了,prompt 如下:
请帮我生成一个 element-ui 表单页面,这个页面有两个选择框,分别是:
选择框el-select 公司(腾讯、百度、阿里)
选择框el-select 产品(QQ、微信、钉钉、淘宝、百度网盘、百度输入法)
其中QQ、微信是腾讯的产品,钉钉、淘宝是阿里的产品,百度网盘、百度输入法是百度的产品。
他们有从属关系,我需要你帮我实现以下功能:
1. 默认情况下,选择框 1 点击可以查看所有的公司选项,选择框 2 可以看到所有的产品选项(不区分公司)。
2. 选择选择框 1 中,任意一个公司后(如:腾讯),选择框 2 中只会出现与该公司(如:腾讯)相关的产品选项。
3. 如果一开始选中的选择框 2的某个产品(如:微信),那么选择框 1 会被默认选中该产品对应的公司(如:腾讯)
4. 再外加一个重置的按钮,点击重置后,两个选择框都恢复到初始状态,也就是单独点击可以查看全部选项。
-----满足上面这些要求后,给我生成一个 bootcdn 版本的element-ui 的html 版本的 demo
于是我们得到了下面的文件内容:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Element UI 表单页面</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
<el-form ref="form" label-position="left" label-width="120px">
<el-form-item label="公司">
<el-select v-model="company" placeholder="请选择公司">
<el-option
v-for="item in companies"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="产品">
<el-select v-model="product" placeholder="请选择产品">
<el-option
v-for="item in products"
:key="item.value"
:label="item.label"
:value="item.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</div>
<script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
company: '',
product: '',
companies: [
{ label: '腾讯', value: 'tencent' },
{ label: '百度', value: 'baidu' },
{ label: '阿里', value: 'alibaba' }
],
products: [
{ label: 'QQ', value: 'qq', company: 'tencent' },
{ label: '微信', value: 'wechat', company: 'tencent' },
{ label: '钉钉', value: 'dingtalk', company: 'alibaba' },
{ label: '淘宝', value: 'taobao', company: 'alibaba' },
{ label: '百度网盘', value: 'baidunetdisk', company: 'baidu' },
{ label: '百度输入法', value: 'baiduinput', company: 'baidu' }
]
};
},
watch: {
company(newValue) {
this.product = '';
if (newValue === 'tencent') {
this.products = [
{ label: 'QQ', value: 'qq', company: 'tencent' },
{ label: '微信', value: 'wechat', company: 'tencent' }
];
} else if (newValue === 'alibaba') {
this.products = [
{ label: '钉钉', value: 'dingtalk', company: 'alibaba' },
{ label: '淘宝', value: 'taobao', company: 'alibaba' }
];
} else if (newValue === 'baidu') {
this.products = [
{ label: '百度网盘', value: 'baidunetdisk', company: 'baidu' },
{ label: '百度输入法', value: 'baiduinput', company: 'baidu' }
];
}
},
product(newValue) {
this.company = newValue.company;
}
},
methods: {
resetForm() {
this.company = '';
this.product = '';
}
}
});
</script>
</body>
</html>
AI 助手虽然给我做出了页面,但是没有替换 cdn,联动还是有问题。不过不要紧,我们来手动实现下功能需求。
从上面代码可以注意到,products 作为第二个选择框的选项,额外引入了company
的字段,这个字段非常关键,当你选中某一项的产品的时候,你能立马知道对应的公司是哪家。真实业务开发过程中,这一点需要跟后端开发沟通,要求对方通过接口返回的数据,包括company
这一项。
仔细想想,其实公司的选项是不需要做过滤的,只有产品需要做过滤。那么思路就很清晰了,如何给产品做过滤,以及如何回显公司。
给产品做过滤,我有两个思路:
其实两个方法思路都是过滤,只是思路2 不需要额外准备一个备份的变量。但思路 2 需要注意一点,v-if 和 v-for 不能混用,这里需要再外层用 template 上加 v-for,然后再在里面加 v-if。
至于公司的选中的回显,只需要在产品选择框上加一个 change 事件,每次改变后,根据当前产品的 value ,用 find 方法查询对应的公司,然后把公司选择框的 v-model 赋值一下就好了。
重置就更好做了,直接用 forEach 把products所有的每一项的 display 设置为 true ,把两个选择框的 v-mol 置为空字符串即可。
另外需要注意一点,每次选择公司后,需要把上次选中的产品给清空掉,我是写完才发现有这个问题的。
下面附上完整的代码吧:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Element UI 表单页面</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
</head>
<body>
<div id="app">
<el-form ref="form" label-position="left" label-width="120px">
<el-form-item label="公司">
<el-select v-model="company" placeholder="请选择公司" @change="handleChange1">
<el-option v-for="item in companies" :key="item.value" :label="item.label" :value="item.value"></el-option>
</el-select>
</el-form-item>
<el-form-item label="产品">
<el-select v-model="product" placeholder="请选择产品" @change="handleChange2">
<template v-for="item in products">
<el-option
v-if="item.display" :key="item.value" :label="item.label" :value="item.value"></el-option>
</template>
</el-select>
</el-form-item>
<el-form-item>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
</div>
<script src="https://unpkg.com/vue@2.6.12/dist/vue.js"></script>
<script src="https://unpkg.com/element-ui@2.15.7/lib/index.js"></script>
<script>
new Vue({
el: '#app',
data() {
return {
company: '',
product: '',
companies: [
{ label: '腾讯', value: 'tencent' },
{ label: '百度', value: 'baidu' },
{ label: '阿里', value: 'alibaba' }
],
products: [
{ label: 'QQ', value: 'qq', company: 'tencent' },
{ label: '微信', value: 'wechat', company: 'tencent' },
{ label: '钉钉', value: 'dingtalk', company: 'alibaba' },
{ label: '淘宝', value: 'taobao', company: 'alibaba' },
{ label: '百度网盘', value: 'baidunetdisk', company: 'baidu' },
{ label: '百度输入法', value: 'baiduinput', company: 'baidu' }
]
};
},
created() {
this.products.forEach(item => item.display = true)
},
methods: {
// 选择公司
handleChange1(value) {
// 根据公司过滤产品,用 forEach 过滤
this.products.forEach(item => item.display = item.company == value)
// 重置产品
this.product = '';
},
// 选择产品
handleChange2(value) {
// 找到选中的那一项
const findProduct = this.products.find(item => item.value === value);
// 把这一项的对应的公司,赋值给 company(注意:这里要加个判断,不然undefined 再取值会报错)
if(findProduct){
this.company = findProduct.company;
}
},
resetForm() {
this.company = '';
this.product = '';
this.products.forEach(item => item.display = true)
}
}
});
</script>
</body>
</html>
实现效果如下:
这样一来,该有的功能就都实现了,用户体验也会比好很多。如果只需要选择产品的话,可以试试级联选择器,改天我写一篇关于级联选择器的文章。
即使面对一个小案例,实现起来也可能存在一些细节需要注意。稍不留神,就有可能出现各种问题。本文根据我个人在实际业务场景中的需求,设计了一个小案例作为模拟。希望通过这个案例的分享能够为你提供一些帮助和启发。愿这个案例也能够激发更多类似的实际应用场景的思考和探讨。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。