ホームページ  >  記事  >  ウェブフロントエンド  >  Vue を使用して都市セレクターを実装するにはどうすればよいですか?

Vue を使用して都市セレクターを実装するにはどうすればよいですか?

WBOY
WBOYオリジナル
2023-06-25 13:43:261311ブラウズ

近年、フロントエンド技術は常に更新されており、フロントエンドフレームワークの登場により日々の開発効率も大幅に向上しています。 Vue.js のフレームワークの下では、都市セレクターなど、一般的に使用される多くの機能コンポーネントを簡単に実装できます。

それでは、Vue で都市セレクターを実装するにはどうすればよいでしょうか?この記事では、簡単な実装方法を紹介します。

1. データの準備

都市セレクターを実装する前に、都市データを準備する必要があります。都市データは大量にあるため、JSON データ形式を使用して保存する必要があります。ここでは、オンラインまたは他のリソースで見つかる JSON データ ファイルを提供します。

都市データ ファイル サンプル:

[
  {
    "label": "北京市",
    "value": "110000",
    "children": [
      {
        "label": "北京市",
        "value": "110100",
        "children": [
          {
            "label": "东城区",
            "value": "110101"
          },
          {
            "label": "西城区",
            "value": "110102"
          },
          {
            "label": "崇文区",
            "value": "110103"
          },
          ...
        ]
      }
    ]
  },
  {
    "label": "上海市",
    "value": "310000",
    "children": [
      {
        "label": "上海市",
        "value": "310100",
        "children": [
          {
            "label": "黄浦区",
            "value": "310101"
          },
          {
            "label": "徐汇区",
            "value": "310104"
          },
          {
            "label": "长宁区",
            "value": "310105"
          },
          ...
        ]
      }
    ]
  },
  ...
]

2. セレクター コンポーネントの実装

2.1 都市データの導入

スクリプト部分に導入する必要があります。コンポーネント都市データ:

<script>
  import cityData from './city-data.json';

  export default {
    // 组件属性和方法
  }
</script>

2.2 セレクター コンポーネントの定義

都市セレクターは複数の場所で使用できるため、コンポーネントとして定義できます。このコンポーネントでは、いくつかのプロパティとメソッドを定義する必要があります。

属性:

  • modelValue: 現在選択されている都市の値;
  • プレースホルダー: セレクター入力ボックスのプロンプト;
  • width: 幅:セレクター入力ボックス;
  • disabled: セレクターが無効かどうか;
  • readonly: セレクターが読み取り専用かどうか。

メソッド:

  • handleChangeCity: 都市を選択した後のコールバック メソッド。
<template>
  <div class="city-picker">
    <input type="text" :readonly="readonly" :disabled="disabled" :placeholder="placeholder" :style="{width: width}" v-model="selectedCity">
    <!-- 其他相关 DOM 结构 -->
  </div>
</template>

<script>
  import cityData from './city-data.json';

  export default {
    props: {
      modelValue: {
        type: String,
        default: ''
      },
      placeholder: {
        type: String,
        default: '请选择城市'
      },
      width: {
        type: String,
        default: '200px'
      },
      disabled: {
        type: Boolean,
        default: false
      },
      readonly: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        selectedCity: this.modelValue,
        // 城市数据
        cityData: []
      }
    },
    methods: {
      handleChangeCity(value) {
        this.selectedCity = value;
        // 触发父组件的 onChange 事件
        this.$emit('onChange', value);
      }
    },
    mounted() {
      this.cityData = cityData;
    }
  }
</script>

2.3 都市データのレンダリング

セレクターで都市データを表示するには、再帰的レンダリングが必要です。レンダリング時に、各レイヤーの都市データを再帰的に走査する関数を定義する必要があります。都市データには複数のレベルがある場合があるため、それを再帰的に走査する必要があります。コードの実装では、レンダリング用の Vue コンポーネントで定義されたテンプレートを使用します。

<template>
  <div>
    <!-- 递归渲染省份数据 -->
    <template v-for="province in cityData">
      <div :key="province.value" class="province">
        <div @click="handleShowCity(province)">{{ province.label }}</div>
        <template v-if="province.children && province.children.length > 0">
          <div v-show="province.showCity">
            <!-- 递归渲染城市和区县数据 -->
            <template v-for="city in province.children">
              <div :key="city.value" class="city">
                <div @click="handleShowDistrict(city)">{{ city.label }}</div>
                <template v-if="city.children && city.children.length > 0">
                  <div v-show="city.showDistrict">
                    <div v-for="district in city.children" :key="district.value">{{ district.label }}</div>
                  </div>
                </template>
              </div>
            </template>
          </div>
        </template>
      </div>
    </template>
  </div>
</template>

<script>
  import cityData from './city-data.json';

  export default {
    props: {
      modelValue: {
        type: String,
        default: ''
      },
      placeholder: {
        type: String,
        default: '请选择城市'
      },
      width: {
        type: String,
        default: '200px'
      },
      disabled: {
        type: Boolean,
        default: false
      },
      readonly: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        selectedCity: this.modelValue,
        // 城市数据
        cityData: []
      }
    },
    methods: {
      handleShowCity(province) {
        // 点击省份时,展开或关闭城市数据
        province.showCity = !province.showCity;
      },
      handleShowDistrict(city) {
        // 点击城市时,展开或关闭区县数据
        city.showDistrict = !city.showDistrict;
        // 选中城市后,调用 handleChangeCity 方法
        this.handleChangeCity(city.label);
      },
      handleChangeCity(value) {
        this.selectedCity = value;
        // 触发父组件的 onChange 事件
        this.$emit('onChange', value);
      },
      // 递归遍历城市数据,渲染出每一个层级的城市数据
      renderCity(cityData) {
        cityData.forEach(city => {
          city.showDistrict = false;
          if (city.children && city.children.length > 0) {
            this.renderCity(city.children);
            city.showCity = false;
          }
        })
      }
    },
    mounted() {
      this.cityData = cityData;
      // 渲染城市数据
      this.renderCity(this.cityData);
    }
  }
</script>

2.4 完全なセレクター コンポーネント コード

最終的な都市セレクター コンポーネント コードは次のとおりです:

<template>
  <div class="city-picker">
    <input type="text" :readonly="readonly" :disabled="disabled" :placeholder="placeholder" :style="{width: width}" v-model="selectedCity">
    <!-- 城市选择器弹出框 -->
    <div class="city-picker-modal" v-show="showModal">
      <div class="city-picker-header">
        <span>请选择城市</span>
        <span class="close-icon" @click="handleCloseModal">&times;</span>
      </div>
      <div class="city-picker-body">
        <!-- 渲染城市选择器树形结构 -->
        <div class="city-picker-tree">
          <div class="top-tab">
            <div
              :class="{ active: (activeTab === 'province') }"
              @click="handleToggleTab('province')"
            >省份</div>
            <div
              :class="{ active: (activeTab === 'city') }"
              @click="handleToggleTab('city')"
            >城市</div>
            <div
              :class="{ active: (activeTab === 'district') }"
              @click="handleToggleTab('district')"
            >区县</div>
          </div>
          <div class="tab-content">
            <template v-if="activeTab === 'province'">
              <!-- 渲染省份数据 -->
              <template v-for="province in cityData">
                <div :key="province.value" class="province">
                  <div @click="handleShowCity(province)">{{ province.label }}</div>
                  <template v-if="province.children && province.children.length > 0">
                    <div v-show="province.showCity">
                      <!-- 渲染城市数据 -->
                      <template v-for="city in province.children">
                        <div :key="city.value" class="city">
                          <div @click="handleShowDistrict(city)">{{ city.label }}</div>
                          <template v-if="city.children && city.children.length > 0">
                            <div v-show="city.showDistrict">
                              <!-- 渲染区县数据 -->
                              <div v-for="district in city.children" :key="district.value">{{ district.label }}</div>
                            </div>
                          </template>
                        </div>
                      </template>
                    </div>
                  </template>
                </div>
              </template>
            </template>
            <template v-else-if="activeTab === 'city'">
              <!-- 渲染城市数据 -->
              <template v-for="province in cityData">
                <template v-if="province.children && province.children.length > 0">
                  <template v-for="city in province.children">
                    <div :key="city.value" class="city">{{ city.label }}</div>
                  </template>
                </template>
              </template>
            </template>
            <template v-else-if="activeTab === 'district'">
              <!-- 渲染区县数据 -->
              <template v-for="province in cityData">
                <template v-if="province.children && province.children.length > 0">
                  <template v-for="city in province.children">
                    <template v-if="city.children && city.children.length > 0">
                      <template v-for="district in city.children">
                        <div :key="district.value">{{ district.label }}</div>
                      </template>
                    </template>
                  </template>
                </template>
              </template>
            </template>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
  import cityData from './city-data.json';

  export default {
    props: {
      modelValue: {
        type: String,
        default: ''
      },
      placeholder: {
        type: String,
        default: '请选择城市'
      },
      width: {
        type: String,
        default: '200px'
      },
      disabled: {
        type: Boolean,
        default: false
      },
      readonly: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        // 当前选中的城市
        selectedCity: this.modelValue,
        // 城市数据
        cityData: [],
        // 显示弹出框标志位
        showModal: false,
        // 当前显示的 tab 标签页
        activeTab: 'province'
      }
    },
    methods: {
      // 选中省份时,展开或关闭城市数据
      handleShowCity(province) {
        province.showCity = !province.showCity;
        this.activeTab = (province.showCity ? 'city' : 'province');
      },
      // 选中城市时,展开或关闭区县数据,并选中城市
      handleShowDistrict(city) {
        city.showDistrict = !city.showDistrict;
        this.activeTab = (city.showDistrict ? 'district' : 'city');
        this.selectedCity = city.label;
        // 触发父组件 onChange 事件
        this.$emit('onChange', city.label);
        // 关闭弹出层
        this.showModal = false;
      },
      // 切换 tab 标签页
      handleToggleTab(tab) {
        this.activeTab = tab;
      },
      // 关闭城市选择器弹窗
      handleCloseModal() {
        this.showModal = false;
      }
    },
    mounted() {
      this.cityData = cityData;
      // 递归渲染城市数据,设置状态
      this.cityData.forEach((province) => {
        province.showCity = false;
        if (province.children && province.children.length > 0) {
          province.children.forEach((city) => {
            city.showDistrict = false;
          })
        }
      })
    }
  }
</script>

3.「都市セレクターの使用」の都市セレクターを使用します

Vue プロジェクトの都市セレクター コンポーネントは非常にシンプルで、使用するページに都市セレクター コンポーネントを導入し、使用時に対応するパラメーターを渡すだけです。以下はコード例です:

<template>
  <div>
    <CityPicker
      v-model="city"
      :width="200"
    ></CityPicker>
  </div>
</template>

<script>
  import CityPicker from './components/CityPicker';

  export default {
    components: {
      CityPicker
    },
    data() {
      return {
        city: ''
      }
    },
    methods: {
      handleChangeCity(value) {
        console.log('选中的城市为:', value);
      }
    }
  }
</script>

この時点で、Vue アプリケーションで都市セレクター コンポーネントをすでに使用できます。この都市セレクター コンポーネントのコードは非常にシンプルですが、基本的な都市選択機能が実装されており、独自のニーズに応じて拡張および最適化できます。

以上がVue を使用して都市セレクターを実装するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。