代码分为HTML、CSS和Vue.js部分,我们逐步解释其功能:
Vue实例数据
Vue实例方法
以上是HTML部分的解释,接下来将继续解释CSS和Vue.js部分,并生成完整的md文档
-
HTML部分:
input
标签和一个搜索按钮,用于输入和搜索地区关键字。- 一个包含地区选择功能的
div
,其中包含了一个左侧地区列表(使用ul
和li
元素构建)和一个右侧的字母索引列表(使用ul
和li
元素构建)。
-
CSS部分:
- 定义了一些基本样式,包括布局和颜色。
- 地区选择列表使用了Flex布局。
-
Vue.js部分:
- 在
data
中定义了city
,keyword
,AZ
和province
等数据。 - 在
mounted
钩子中,调用getCity
和getAZ
方法初始化数据。 getCity
方法通过发送网络请求获取城市数据,然后缓存到本地,并初始化province
数据。getAZ
方法生成了A到Z的字母索引数组AZ
。toTargetPage
方法用于点击字母索引时滚动到对应的地区。search
方法用于实现地区搜索功能,根据用户输入的关键字过滤地区数据,并更新city
的值。
- 在
-
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <!-- 引入vue --> <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script> <title>Document</title> <style> * { margin: 0; padding: 0; } .area-warpper { display: flex; } .left { flex: 1; } .left li { list-style: none; padding: 10px; border-bottom: 1px solid #f7f7f7; } .right { flex-shrink: 0; background-color: #ccc; width: 60px; background: #ccc; color: #fff; display: flex; flex-direction: column; justify-content: center; align-items: center; align-self: baseline; /* margin-top: 80px; */ list-style: none; position: fixed; right: 0; top: 0; box-shadow: 0 0 10px #ccc; /* min-height: 100vh; */ overflow-y: scroll; /* padding: 0px 0; */ } .right-item { margin-bottom: 4px; padding: 0 10px; border-bottom: #f7f7f7; white-space: nowrap; cursor: pointer; } .search-warpper { position: fixed; top: 0; width: 100vw; height: 20px; padding: 10px; background: #fff; box-shadow: 0 0 10px #ccc; } </style> </head> <body> <div id="app"> <div class="search-warpper"> <input v-model="keyword" type="text" placeholder="请输入关键字" class="searchInput" @keyup.enter="search" /> <button @click="search">搜索</button> </div> <h1 style="margin-top: 50px;">地区选择</h1> <div class="area-warpper"> <div class="left"> <ul> <li v-for="item in city" :key="item.label" style="font-size: 25px;font-weight: bold;" :id="item.label">{{item.label}} <ul v-if="item.children"> <li v-for="item2 in item.children" :key="item2.label" :id="item2.label" style="font-size: 23px;font-weight: bold;">{{item2.label}} <ul v-if="item2.children"> <li v-for="(item3) in item2.children" :key="item3.label" :id="item3.label" style="font-weight: normal;font-size: 16px;cursor: pointer;"> {{item3.label}} <ul v-if=" item3.children"> <li v-for="item4 in item3.children" :id="item4.label" :key="item4.label"> {{item4.label}}</li> </ul> </li> </ul> </li> </ul> </li> </ul> </div> <ul class="right"> <!-- <li v-for="item in AZ" :key="item" class="right-item">{{item}}</li> --> <li v-for="item in province" :key="item" class="right-item" @click="toTargetPage(item)">{{item.label}} </li> </ul> </div> </div> </body> <script> window.baseUrl = 'https://pre.lvsetk.com' const vm = new Vue({ el: '#app', data: { city: [], keyword: '', AZ: [], province: [], }, mounted() { this.getCity(); // this.getCityByIp(); this.getAZ() console.log(this.AZ) }, methods: { toTargetPage({ value: item }) { window.location.href = '#' + item }, // 实现一个获取A到Z的方法 getAZ() { const arr = [] for (let i = 65; i <= 90; i++) { arr.push(String.fromCharCode(i)) } this.AZ = arr }, async getProvince() { if (this.city.length > 0) { this.province = this.city.map(item => { return { label: item.label, value: item.value } }) console.log(this.province, 'province') return } }, async getCity() { // 缓存本地 const city = sessionStorage.getItem('city') if (city) { this.city = JSON.parse(city) this.getProvince() return } const { success, result } = await fetch(window.baseUrl + '/api/front_server/region/getTree').then(res => res.json()); // const { success, result } = await fetch(window.baseUrl + '/api/front_server/region/getProvince').then(res => res.json()); success && (this.city = result) && sessionStorage.setItem('city', JSON.stringify(result)) && this.getProvince() }, async getCityByIp() { const { success, result } = await fetch(window.baseUrl + '/api/front_server/map/queryByIp').then(res => res.json()); success && console.log(result, 'ip') }, search() { this.keyword = this.keyword.trim() console.log(this.keyword) // 过滤掉不包含keyword的数据,重新赋值给city,city 是一个树形结构 // 1.遍历city if (this.keyword) { this.handleFilterCity() } else { this.getCity() } }, handleFilterCity() { this.getCity() const newCity = this.city.filter(item => { // 2.判断当前节点是否包含keyword if (item.label.includes(this.keyword)) { return true } // 3.判断当前节点的子节点是否包含keyword if (item.children) { item.children = item.children.filter(item2 => { if (item2.label.includes(this.keyword)) { return true } if (item2.children) { item2.children = item2.children.filter(item3 => { if (item3.label.includes(this.keyword)) { console.log(item3.label, 'item3') return true } if (item3.children) { item3.children = item3.children.filter(item4 => { console.log(item4, 'item4') if (item4.label.includes(this.keyword)) { return true } }) } }) if (item2.children.length > 0) { console.log(item2.children, 'item2.children') return true } // console.log(item2.children.length, 'item2.children') } }) if (item.children.length > 0) { console.log(item.children, 'item.children') return true } } }) console.log(newCity, 'newCity') this.city = newCity }, } }) </script> </html>
组件结构
search-warpper
: 搜索栏,包含一个输入框和搜索按钮。area-warpper
: 地区选择功能的主要部分,包含左侧地区列表和右侧字母索引列表。left
: 左侧地区列表,使用嵌套ul
和li
元素构建。right
: 右侧字母索引列表,使用嵌套ul
和li
元素构建。
city
: 存储城市数据。keyword
: 存储用户输入的地区关键字。AZ
: 存储A到Z的字母索引数组。mounted
: 在实例挂载后调用,用于初始化数据和获取城市数据。toTargetPage
: 点击字母索引时触发,滚动到对应地区。getAZ
: 生成A到Z的字母索引数组。getCity
: 获取城市数据,可选择缓存到本地。search
: 实现地区搜索功能,根据用户输入的关键字过滤地区数据。province
: 存储地区选择的省份数据。