js实现二级联动(包括js、vue、react+ts、vue3+ts的写法)

JavaScript 实现二级联动是一个常见的前端开发任务,下面给出一种基础的实现方式。

HTML 代码部分:

html
<!-- 省份选择器 -->
<select id="province">
  <option value="">请选择省份</option>
  <option value="浙江省">浙江省</option>
  <option value="广东省">广东省</option>
</select>

<!-- 城市选择器 -->
<select id="city" disabled>
  <option value="">请先选择省份</option>
</select>

上述代码中包含了两个 元素,一个表示省份选择器,一个是城市选择器,首先将城市选择器禁用,直到用户选择具体省份时才启用。

JavaScript 代码部分:

javascript
const provinceSelect = document.getElementById('province');
const citySelect = document.getElementById('city');

const cities = [
  { province: '浙江省', name: '杭州市' },
  { province: '浙江省', name: '宁波市' },
  { province: '浙江省', name: '温州市' },
  { province: '广东省', name: '广州市' },
  { province: '广东省', name: '深圳市' },
  { province: '广东省', name: '珠海市' }
];

// 根据所选省份生成城市选项
function generateCityOptions() {
  // 获取当前所选省份的值
  const province = provinceSelect.value;
  // 清空原有城市选项
  clearCityOptions();
  // 生成新的城市选项
  for (let i = 0; i < cities.length; i++) {
    const city = cities[i];
    if (city.province === province) {
      const option = document.createElement('option');
      option.value = city.name;
      option.text = city.name;
      citySelect.appendChild(option);
    }
  }
  // 启用城市选择器
  citySelect.disabled = false;
}

// 清空城市选项
function clearCityOptions() {
  while (citySelect.firstChild) {
    citySelect.removeChild(citySelect.firstChild);
  }
  // 禁用城市选择器
  citySelect.disabled = true;
}

provinceSelect.addEventListener('change', function(event) {
  generateCityOptions();
});

generateCityOptions();

上述代码使用了一个名为 cities 的数组存储了所有可选的城市数据。在 generateCityOptions() 函数中根据当前所选省份的值,筛选出对应的城市,然后将它们逐一添加到城市选择器中,并启用该选择器。在 clearCityOptions() 函数中则是清空已有的城市选项,以及禁用该选择器。

最后,通过将 generateCityOptions() 方法绑定到省份选择器的 change 事件上,这样当用户选择省份时就会自动调用该方法,生成相应的城市选项。

以上代码实现了简单的二级联动,可以根据需求进行二次优化和扩展。

vue的写法

下面是基于 Vue 的二级联动的实现方式,采用了 Vue 组件和数据绑定的方式。

HTML 代码部分:

html
<div id="app">
  <!-- 省份选择器 -->
  <select v-model="selectedProvince">
    <option value="">请选择省份</option>
    <option v-for="province in provinces" :key="province" :value="province">{{ province }}</option>
  </select>

  <!-- 城市选择器 -->
  <select v-model="selectedCity" :disabled="!selectedProvince">
    <option value="">请先选择省份</option>
    <option v-for="city in cities" :key="city" :value="city">{{ city }}</option>
  </select>
</div>

上述代码中使用了 v-model 指令将选择器的值与 Vue 实例中的数据进行双向绑定,同时也使用了 v-for 指令遍历数组中的每个元素生成具体的选项。在城市选择器中使用了 :disabled 属性,当未选择省份时禁用该选择器。

JavaScript 代码部分:

javascript
new Vue({
  el: '#app',
  data: {
    provinces: ['浙江省', '广东省'],
    selectedProvince: '',
    cities: []
  },
  watch: {
    // 监听选中省份变化
    selectedProvince: function(newValue, oldValue) {
      if (newValue) {
        this.getCities(newValue);
      } else {
        this.cities = [];
      }
      this.selectedCity = '';
    }
  },
  methods: {
    // 根据所选省份获取城市数据
    getCities: function(province) {
      // 模拟异步请求
      setTimeout(() => {
        if (province === '浙江省') {
          this.cities = ['杭州市', '宁波市', '温州市'];
        } else if (province === '广东省') {
          this.cities = ['广州市', '深圳市', '珠海市'];
        }
      }, 500);
    }
  }
});

上述代码中使用了 Vue 实例的 data 属性用来存储组件中所需的数据,其中 provinces 存储所有可选省份、selectedProvince 表示当前所选择的省份、cities 则表示当前省份下可选的所有城市。此外,还定义了一个 watch 属性监控所选省份的变化,并在其发生改变时调用 getCities() 方法获取相应城市数据,最后将得到的数据更新到 cities 变量中。

需要注意的是,这里通过 setTimeout() 方法模拟异步请求,在实际开发中可以使用 Ajax 等技术来从服务端获取数据,具体实现方式视实际情况而定。

以上就是利用 Vue 实现二级联动的代码实现方式,Vue 的组件化封装和数据绑定机制能够提高开发效率,使得代码更加简洁易读。

react+ts写法

以下是基于 React 和 TypeScript 的二级联动的实现方式。

首先,需要为 Option 接口定义一个数据类型:

typescript
interface Option {
  value: string;
  label: string;
}

然后定义一个叫做 CitySelect 的函数式组件来渲染城市选择器:

typescript
import React, { useState } from 'react';

interface Props {
  provinces: Option[];
  cities: Record<string, string[]>;
}

function CitySelect({ provinces, cities }: Props) {
  const [selectedProvince, setSelectedProvince] = useState('');
  const provinceOptions = [{ value: '', label: '请选择省份' }, ...provinces];
  const cityOptions = [{ value: '', label: '请先选择省份', disabled: true }];

  if (selectedProvince && cities[selectedProvince]) {
    for (let i = 0; i < cities[selectedProvince].length; i++) {
      const city = cities[selectedProvince][i];
      cityOptions.push({ value: city, label: city });
    }
  }

  function handleProvinceChange(event: React.ChangeEvent<HTMLSelectElement>) {
    setSelectedProvince(event.target.value);
  }

  return (
    <>
      <select value={selectedProvince} onChange={handleProvinceChange}>
        {provinceOptions.map(option => (
          <option key={option.value} value={option.value}>{option.label}</option>
        ))}
      </select>
      <select value={''} disabled={!selectedProvince}>
        {cityOptions.map(option => (
          <option
            key={option.value}
            value={option.value}
            disabled={option.disabled}
          >{option.label}</option>
        ))}
      </select>
    </>
  );
}


export default CitySelect;

上述代码中使用了 React 的 Hooks 写法,利用 useState 来存储当前所选省份的值,并将其与省份选择器的 value 属性进行绑定,以便在用户选择项时获取到最新的省份数据。同时也定义了两个数组,provinceOptions 存储所有可选的省份,cityOptions 用来动态渲染城市选择器,并控制其启用或禁用状态。

在组件中还定义了一个 handleProvinceChange() 方法来处理省份选择器的变化,并更新当前所选省份的值。该方法被绑定到省份选择器的 onChange 事件上,一旦用户操作省份选择器,则会自动调用该方法。

最后,使用 map() 方法遍历数据,生成相应的 元素。当用户选择省份时,会根据对应城市数据动态渲染城市选择器的选项,并启用该选择器;当用户没有选择省份时,则不能通过城市选择器选择任何选项。

至此,React + TypeScript 实现二级联动就完成了。

vue3+ts写法

以下是基于 Vue 3 和 TypeScript 的二级联动的实现方式。

首先,需要为 Option 接口定义一个数据类型:

typescript
interface Option {
  value: string;
  label: string;
}

然后,在 src 目录下新建一个名为 CitySelect.vue 的组件文件,并在其中编写如下代码:

<template>
  <div>
    <select v-model="selectedProvince" @change="handleProvinceChange">
      <option value="" disabled selected>请选择省份</option>
      <option v-for="province in provinceOptions" :value="province.value" :key="province.value">{{ province.label }}</option>
    </select>
    <select :disabled="!selectedProvince">
      <option value="" disabled>{{ selectedProvince ? '请选择城市' : '请先选择省份' }}</option>
      <option v-for="city in cityOptions" :value="city.value" :key="city.value">{{ city.label }}</option>
    </select>
  </div>
</template>

<script lang="ts">
import { defineComponent, ref } from 'vue';

interface Props {
  provinces: Option[];
  cities: Record<string, string[]>;
}

export default defineComponent({
  name: 'CitySelect',
  props: {
    provinces: {
      type: Array as () => Option[],
      required: true
    },
    cities: {
      type: Object as () => Record<string, string[]>,
      required: true
    }
  },
  setup(props: Props) {
    const selectedProvince = ref('');
    const provinceOptions = [{ value: '', label: '请选择省份' }, ...props.provinces];
    const cityOptions = [{ value: '', label: selectedProvince.value ? '请先选择省份' : '请选择城市', disabled: true }];

    function handleProvinceChange(event: Event) {
      const target = event.target as HTMLSelectElement;
      selectedProvince.value = target.value;
      cityOptions.splice(2, cityOptions.length - 2);
      if (selectedProvince.value && props.cities[selectedProvince.value]) {
        for (let i = 0; i < props.cities[selectedProvince.value].length; i++) {
          const city = props.cities[selectedProvince.value][i];
          cityOptions.push({ value: city, label: city });
        }
      }
    }

    return {
      selectedProvince,
      provinceOptions,
      cityOptions,
      handleProvinceChange
    };
  }
});
</script>

上述代码中定义了一个名为 CitySelect 的 Vue 组件来渲染城市选择器。在组件中使用了 ref 创建了一个响应式的 selectedProvince 变量,用于存储当前所选省份的值,并将其与省份选择器的 v-model 指令进行绑定。

同时也定义了两个数组,provinceOptions 存储所有可选的省份,cityOptions 用来动态渲染城市选择器,并控制其启用或禁用状态。为了保证正确性,需要在选项列表的第一个位置分别加入“请选择省份”和“请选择城市”这两个选项。

在组件中还定义了一个 handleProvinceChange() 方法来处理省份选择器的变化,并通过调用 props.cities 对象来获取到对应的城市数据源,并更新 cityOptions 数组内容。该方法被绑定到省份选择器的 change 事件上,一旦用户操作省份选择器,则会自动调用该方法。

最后,在使用这个组件的地方,只需要将 provinces 和 cities 这两项数据传递给组件即可,例如:

<template>
  <CitySelect :provinces="provinces" :cities="cities" />
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import CitySelect from '@/components/CitySelect.vue';

interface Province {
  name: string;
  code: string;
}

export default defineComponent({
  name: 'App',
  components: {
    CitySelect
  },
  data() {
    return {
      provinces: [{ value: '', label: '请选择省份' }, { value: 'gd', label: '广东省' }],
      cities: {
        gd: ['广州市', '深圳市']
      }
    };
  }
});
</script>

由于在 CitySelect.vue 组件中已经定义了 props 接口规范,因此在使用组件时需要传入与之匹配的 provinces 和 cities 数据。在本例中,例子数据中包含一个名为 provinces 的数组和一个名为 cities 的对象。其中 provinces 是一个包含所有可选省份的选项列表,而 cities 则是一个字典对象,键名为省份的代码,对应的值为一个包含该省份下所有可选城市名称的字符串数组。

至此,Vue 3 + TypeScript 实现二级联动就完成了。如果想要上线发布项目,可以执行 npm run build 命令来生成最终的生产版代码。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值