首頁 > web前端 > Vue.js > 如何使用 Vue 實現城市選擇器?

如何使用 Vue 實現城市選擇器?

WBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWBOYWB
發布: 2023-06-25 13:43:26
原創
1734 人瀏覽過

近年來,前端技術不斷更新,前端框架的出現也讓我們日常開發中效率得到很大的提升。在 Vue.js 的框架下,我們可以輕易地實作許多常用的功能元件,例如城市選擇器。

那麼,如何在 Vue 中實現城市選擇器呢?本篇文章將給大家分享一個簡單的實作方法。

一、資料準備

在實現城市選擇器之前,我們需要準備好城市資料。由於城市資料比較多,我們需要使用一個 JSON 資料格式來儲存。在這裡,我提供了一個 JSON 資料文件,大家可以在網路或其他資源中尋找。

城市資料檔案範例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

[

  {

    "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.1 引入城市資料

我們需要在元件的script 部分引入城市資料:

1

2

3

4

5

6

7

<script>

  import cityData from './city-data.json';

 

  export default {

    // 组件属性和方法

  }

</script>

登入後複製

2.2 定義選擇器元件

由於城市選擇器可以用於多個地方,我們可以將它定義為一個元件。在這個元件中,我們需要定義一些屬性和方法。

屬性:

  • modelValue:目前選取的城市值;
  • placeholder:選擇器輸入方塊中的提示語;
  • ##width:選擇器輸入框的寬度;
  • disabled:選擇器是否停用;
  • readonly:選擇器是否唯讀。
方法:

    handleChangeCity:選取城市後的回呼方法。
  • 1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    <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 的方式進行渲染。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

<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 完整選擇器元件代碼

最終的城市選擇器元件代碼如下所示:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

<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>

登入後複製

三、使用城市選擇器

在Vue 專案中的使用城市選擇器元件很簡單,只需要在需要使用的頁面中引入城市選擇器元件,然後在使用時傳入相應的參數即可。以下是使用程式碼範例:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

<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中文網其他相關文章!

相關標籤:
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板