❤ 项目源码 ❤
GitHub地址:https://github.com/Umbrella001/mtapp
切换城市
1.1 实现图
1.2 组件化结构,使用多组件页进行合并拼凑
1.3 省市二级联动如何做?
依靠E-UI完成界面后,我们开始写逻辑交互
最后完成的template:
<div class="m-iselect">
<span class="name">按省份选择:</span>
<el-select v-model="pvalue" placeholder="省份">
<el-option
v-for="item in province"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
<el-select v-model="cvalue" :disabled="!city.length" placeholder="城市">
<el-option v-for="item in city" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<span class="name"> 中文搜索:</span>
<el-autocomplete
v-model="input"
:fetch-suggestions="querySearchAsync"
placeholder="请输入城市中文或拼音"
@select="handleSelect"
></el-autocomplete>
</div>
首先明确一载入切换城市界面,哪个是要进行请求的,那就是省份(第一级),此时可以使用ssr进行服务端渲染,页面载入后也跟着进行载入,但这里就直接使用vue中的Mouted生命函数完成这里的axios请求 ↓
mounted: async function() {
let self = this;
let {
status,
data: { province }
} = await self.$axios.get("/geo/province");
if (status === 200) {
self.province = province.map(item => {
return {
value: item.id,
label: item.name
};
});
}
}
这样一来就完成了一级的就绪,然后二级市区的选择在没有选择省份时是不会触发的,所以可以使用E-UI中的disable进行禁选;
好了我们开始做联动逻辑,使用watch监听用户选择了什么省份 ↓
watch: {
pvalue: async function(newPvalue) {
let self = this;
let {
status,
data: { city }
} = await self.$axios.get(`/geo/province/${newPvalue}`);
if (status === 200) {
self.city = city.map(item => {
return {
value: item.id,
label: item.name
};
});
self.cvalue = "";
}
}
}
这种数据(由用户决定的数据),就需要使用watch监听,只要写在里面的函数发生了改变就会执行,而这里恰恰可以用v-model绑定的值作为监听的值,当用户选择省份时就会异步请求接口,注意这里传入的值跟监听的pvalue是一样的,根据mounted的请求可以知道pvalue就是对应省级的id,你可能会问,那我v-model绑定的是输入框的值,明显这里的请求参数不是中文地名呀,注意了这里就是select下拉框的设计,如果你不设置label显示的还是value的值,但是如果你设置了label那输入框显示的就是label的值,但是你v-model拿的还是你value的值,所以在省份中复制也是将id赋值给value的,所以参数正确!
会二级联动,三级联动还会难吗?毕竟现在你只需要重点思考逻辑上的代码,而DOM结构E-UI已经随随便便完成了,只剩下你关联他们的代码而已
1.4 如何利用Element-UI完成项目中的远程搜索?
分析:
凡是涉及地区的项目,肯定都是有远程搜索之说,一旦提到用户搜索务必都使用延迟节流处理,一般实时搜索的节流处理,目前就我知道可以使用lodash里的延迟函数debounce
远程搜索参数解析:
首先来解释一下E-UI中的远程搜索的DOM属性,只有你了解他上面的函数节点属性的意思你才能去写逻辑,首先v-model="input"
绑定的是谁,不就是输入框咯;`querySearchAsync`当用户输入后触发,这里就可以写请求参数的接口;handleSelect
选中时触发
重要点点讲:
① 延迟函数就是异步,反正异步函数就给我写返回值,所以参数很明确,必须有返回值(这里一参为搜索项,二参为回调也就是返回值)
② 凡是数组中还带条件筛选的就给我写filter就完事了,还有filter不写成es6的都是耍流氓!
③ 如果数组中不带条件筛选的还需要遍历的,map+箭头函数 了解一下
④ 关于根据用户中文或者英文搜索都可以搜索对应的数据出来(升级可拼音)
methods: {
querySearchAsync: _.debounce(async function(query, callback) {
let self = this;
if (self.cities.length) {
callback(self.cities.filter(item => item.value.indexOf(query) > -1 || item.charValue.indexOf(query) > -1));
} else {
let {
status,
data: { city }
} = await self.$axios.get("/geo/city");
if (status === 200) {
self.cities = city.map(item => {
return {
value: item.name,
charValue: pyjs.getFullChars(item.name).toLocaleLowerCase()
};
});
callback(self.cities.filter(item => item.value.indexOf(query) > -1 || item.charValue.indexOf(query) > -1));
} else {
callback([]);
}
}
}, 200),
关于展示热门城市的那栏逻辑和DOM结构都很简单,简述复习一下:
首先说一下这种结构的DOM结构只需要几个DOM节点就完成:
dl>dd+dt
<div class="m-hcity">
<dl>
<dd>热门城市:</dd>
<dt
v-for="item in list"
:key="item.id"
>{{item.name === '市辖区'? item.province: item.name}}</dt>
</dl>
</div>
其次就是逻辑,既然使用nuxt就好好利用async和await配合请求接口:
这里强调两点:
① async mounted(){ } 和 mounted: async function(){ } 是一样的
② 用了那么多次解构赋值版的请求接口,你应该知道state{}花括号了是什么了把,看下面的图,如果还不知道翻翻之前的请求~!
1.5 城市根据首字母分类
重点:关于将城市按拼音首字母分类 ,两种一种就是后端给个标识给你帮你分类(一般不多,靠后端还不如靠自己),第二种就是前端怎么自己去做(重点学习!!!)
重要的几点 :
① 使用第三方插件库,目前唯一最方便的做法 npm install js-pinyin
,在需要使用该插件的地方导入即可 import pyjs from 'js-pinyin'
② 关于循环26个字母你会怎么做?数组中一个一个写吗,首先DOM结构中使用循环肯定是必须的,这是就是如何设计你的循环的数组 ↓ 整个字符串写好A-Z然后用split分割成数组
<div>
<!-- 字母导航栏 -->
<dl class="m-categroy">
<dt>按拼音首字母选择:</dt>
<dd
v-for="item in list"
:key="item"
>
<a :href="'#city-' + item">{{ item }}</a>
</dd>
</dl>
<!-- 字母城市展示栏 -->
<dl
v-for="item in block"
:key="item.title"
class="m-catagroy-section">
<dt :id="'city-' + item.title">{{item.title}}</dt>
<dd>
<span
v-for="c in item.city"
:key="c"
>
{{ c }}
</span>
</dd>
</dl>
</div>
data(){
return{
list:'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')
}
}
③ 如何结合js-pinyin插件库拿到中文数据的全拼
插件库中就有一个方法为getFullChars,它接受的参数就是中文数据,返回值就是该中文数据对应的全拼
PS:注意getFullChars拿到的是一种如(北京:BeiJing)的首字母大写,所以可以根据需求全转大写或小写,亦可以通过Ascll值配合split拿到首字母大写,总之根据需求去写逻辑即可
pyjs.getFullChars(item.name).toLocaleLowerCase().slice(0,1);
④ 如何将对应的城市放进对应的字母数组中?
只需要这样一段if判断就完事了,怎么实现?
首先简单的做一下a-z小写字母的Ascrll码值的判断(怎么来的? 通过string.charCodeAt(0)拿到了首个字符的ASCLL值)
然后通过判断cityCharAll对象中是否有该键名 → 如果没有则在空对象中创建储存一个键值对 | OR | 如果有则直接push进去已有的数组
这里就巧在对象中存储的是带有名字的键值对,然后让同一个开头字母的城市Push进对应的字母数组中!完美
if(cityAscll >= 97 && cityAscll <= 124){
if(!cityCharAll[cityChar]){
cityCharAll[cityChar] = []
}
cityCharAll[cityChar].push(item.name)
}
⑤ 通过上面的对号入座,但却还没有排序,如何排列成a-z呢?
为什么突然这样写,这是根据DOM结构去设计的数组,反正页面的元素要循环的,一律放进数组中去给他们循环
for(let [key,value] of Object.entries(cityCharAll)){
blocks.push({
title: key.toUpperCase(),
city: value
})
}
结果如下:
排序:
blocks.sort((x,y) => x.title.charCodeAt(0) - y.title.charCodeAt(0));
self.block = blocks;
直接通过ASCLL码来拍就行,sort()自动会从小到大进行升序排列
Vue中的跳转(根据字母的跳转):
之前用scroll高度去做,其实不必用JS完成,直接使用DOM就可以
加个#锚点就行!还不清楚就去看上面的DOM。这里因为涉及动态数据,所以要加上v-bind:href='xxx' ```→```→```→```→```→```:id='xxx'
<a href="#city-A">A</a>
<div id="city-A">A字母</div>
这样点击字母A就可以跳转到对应的A开头的城市列表
❤ 项目源码 ❤
GitHub地址:https://github.com/Umbrella001/mtapp