前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何实现两个下拉选择框 select选中联动效果?

如何实现两个下拉选择框 select选中联动效果?

原创
作者头像
喵喵侠
修改2024-06-13 16:09:00
2371
修改2024-06-13 16:09:00
举报

目录

前言

最近接到一个需求,大概是这样的:

某一个页面,上面是查询项,下面是列表。查询项中有两个下拉选择框,都是查询条件。这两个选择框是父子级的关系。当我选中第一个选择框某一项时,第二个选择框的下拉项会发生变化;当选择第二个选择框的某一项时,需要回填第一个选择框的值。

大概是这么个效果,这么描述起来有点复杂。下面我们来看一个实际案例,这样就会清晰很多。

案例

假设现在有两个下拉选择框,选择框1代表公司,选择框 2 代表产品。如下图所示:

实现的功能要求如下:

  1. 默认情况下,选择框 1 点击可以查看所有的公司选项,选择框 2 可以看到所有的产品选项(不区分公司)。
  2. 选择选择框 1 中,任意一个公司后(如:腾讯),选择框 2 中只会出现与该公司(如:腾讯)相关的产品选项。
  3. 如果一开始选中的选择框 2的某个产品(如:微信),那么选择框 1 会被默认选中该产品对应的公司(如:腾讯)
  4. 再外加一个重置的按钮,点击重置后,两个选择框都恢复到初始状态,也就是单独点击可以查看全部选项。

通过这个案例描述,加上配图,是不是就清晰许多了。下面我们来一起实现这样的功能吧。

功能实现

首先我们写一个页面布局,可以手写,也可以借助腾讯云 AI 代码助手来生成。

这里我以 element ui 为例子,用 AI 助手来生成了,prompt 如下:

代码语言:vue
复制
请帮我生成一个 element-ui 表单页面,这个页面有两个选择框,分别是:
选择框el-select 公司(腾讯、百度、阿里)
选择框el-select 产品(QQ、微信、钉钉、淘宝、百度网盘、百度输入法)
其中QQ、微信是腾讯的产品,钉钉、淘宝是阿里的产品,百度网盘、百度输入法是百度的产品。
他们有从属关系,我需要你帮我实现以下功能:
1. 默认情况下,选择框 1 点击可以查看所有的公司选项,选择框 2 可以看到所有的产品选项(不区分公司)。
2. 选择选择框 1 中,任意一个公司后(如:腾讯),选择框 2 中只会出现与该公司(如:腾讯)相关的产品选项。
3. 如果一开始选中的选择框 2的某个产品(如:微信),那么选择框 1 会被默认选中该产品对应的公司(如:腾讯)
4. 再外加一个重置的按钮,点击重置后,两个选择框都恢复到初始状态,也就是单独点击可以查看全部选项。
-----满足上面这些要求后,给我生成一个 bootcdn 版本的element-ui 的html 版本的 demo

于是我们得到了下面的文件内容:

代码语言:html
复制
<!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这一项。

仔细想想,其实公司的选项是不需要做过滤的,只有产品需要做过滤。那么思路就很清晰了,如何给产品做过滤,以及如何回显公司。

给产品做过滤,我有两个思路:

  1. 备份一下原有的全量数据,写到 data 里面命名为productsDefault,当选中公司后,将productsDefault用 filter 方法,判断筛选出等于当前公司的项,返回数组并赋值给products。
  2. 还是用原来的 products 这个数组,只是给每一项额外新增一个字段,比方说叫 display,设置为 true 就是显示,设置为 false 就是隐藏,绑定到 el-option上,控制是否渲染。

其实两个方法思路都是过滤,只是思路2 不需要额外准备一个备份的变量。但思路 2 需要注意一点,v-if 和 v-for 不能混用,这里需要再外层用 template 上加 v-for,然后再在里面加 v-if。

至于公司的选中的回显,只需要在产品选择框上加一个 change 事件,每次改变后,根据当前产品的 value ,用 find 方法查询对应的公司,然后把公司选择框的 v-model 赋值一下就好了。

重置就更好做了,直接用 forEach 把products所有的每一项的 display 设置为 true ,把两个选择框的 v-mol 置为空字符串即可。

另外需要注意一点,每次选择公司后,需要把上次选中的产品给清空掉,我是写完才发现有这个问题的。

下面附上完整的代码吧:

代码语言:html
复制
<!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>

实现效果如下:

这样一来,该有的功能就都实现了,用户体验也会比好很多。如果只需要选择产品的话,可以试试级联选择器,改天我写一篇关于级联选择器的文章。

总结

即使面对一个小案例,实现起来也可能存在一些细节需要注意。稍不留神,就有可能出现各种问题。本文根据我个人在实际业务场景中的需求,设计了一个小案例作为模拟。希望通过这个案例的分享能够为你提供一些帮助和启发。愿这个案例也能够激发更多类似的实际应用场景的思考和探讨。


我正在参与2024腾讯技术创作特训营最新征文,快来和我瓜分大奖!

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 目录
  • 前言
  • 案例
  • 功能实现
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档