前言
- 最近没什么事做,用vue仿写elm
- 写完了城市定位选择页面,感觉其他好像都有字母侧边栏可以选择联动
- 我想嗯我也要弄一个城市联动的,然后就开始写
- 但是这个并不是一个简单的过程,因为一个小小的失误导致花费了很长的时间
- 搞了好久搞到烦,最后还是睡了一觉在梦里解决的
工具/资料
- 系统 macOs 10.13.3
- 工具 vs code
- 开发语言 js vue
- 插件 better-scroll,插件地址
- 城市数据接口: http://yhf7.top:3000/api/v1/cities?type=group
注意事项
- axios是我自己封装的需要阅读清楚,使用自己封装的也是可以的,api请求里面的loadding我没有放出来
- better-scroll我使用的是1.x的版本,也是1.x的写法,不知道2.x能不能套用没试过
- 固定好父级高度,不要让子撑开父,这样使得父级和子级高度一样无法获取x,y导致无法滚动(本人就是在这个问题弄了好久最后才发现的)
- 有时候第一次进入插件没有加载好需要刷新才能滚动的这个我也不知道着么破要是你解决的请告诉我
- 数据获取好才初始化结构
开始
1. 获取数据(这里面的代码需要的可以私聊我发这里就不贴出来了)
- 这里我vue里面使用的是axios封装的获取函数,我可以给你们看看和我配置的结构
安装axios、better-scroll
1
$ sudo cnpm i axios better-scroll -S
配置封装axios与接口
- 调用
- 查看数据效果
2. 编写界面 (这里必须是要把需要滚动的父级高度限制小于需要滚动的高度)
- 拿到了数据当然是要把界面编辑处来的啦
- 由于我们是城市而且是所有的按照A-Z排序输出的
- 城市:使用一个ul包裹着li里面嵌套的是一个标题和城市的ul列表
- 侧边栏: 就是一个ul里面li循环所有城市的字母
- ref: 为需要滚动的父级名称,自定义的用来获取元素用的
html
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<!-- 所有城市 -->
<div class="group_city_container mr2" ref="foodsWrapper">
<ul class="letter_classify">
<li
v-for="(value,key,index) in sortgroupcity"
:key="key"
class="letter_classify_li food-list-hook"
>
<h4 class="city_title">
{{key}}
<span v-if="index == 0">(按字母排序可滚动)</span>
</h4>
<ul class="groupcity_name_container citylistul clear">
<router-link
tag="li"
v-for="item in value"
:to="'/city/' + item.id"
:key="item.id"
class="ellipsis"
>{{item.name}}</router-link>
</ul>
</li>
</ul>
</div>
<!-- A-Z右边框列表 -->
<div class="alphabet" ref="menuWrapper">
<ul>
<li
class="item"
v-for="(item,i) in letters"
:key="i"
:class="{'current':currentIndex === i}"
@click="selectMenu(i)"
>{{item}}</li>
</ul>
</div>scss
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.city_title {
color: #666;
font-weight: 400;
text-indent: 0.45rem;
border: 2px solid $bc;
border-width: 2px 0 1px 0;
@include font(0.55rem, 1.45rem, "Helvetica Neue");
span {
@include sc(0.475rem, #999);
}
}
.citylistul {
li {
float: left;
text-align: center;
color: $blue;
border: 2px solid $bc;
border-width: 0 1px 1px 0;
@include wh(25%, 1.75rem);
@include font(0.6rem, 1.75rem);
}
li:nth-of-type(4n) {
border-right: none;
}
}
.letter_classify_li {
margin-bottom: 0.4rem;
background-color: #fff;
border-bottom: 1px solid $bc;
.groupcity_name_container {
li {
color: #666;
}
}
}
// 所有城市
.group_city_container {
height: 23.1rem;
overflow: hidden;
}
// A-z
.alphabet {
display: flex;
justify-content: center;
align-items: center;
position: fixed;
top: 40px;
width: 20px;
right: 0;
bottom: 0;
background: #a5dff9;
z-index: 1;
.item {
text-align: center;
line-height: 20px;
font-size: 12px;
}
.current {
color: red;
}
}
// 公共右margin 20
.mr2 {
margin-right: 20px;
}
3. 相关的js代码,配置滚动
- 获取添加所有的城市的字母
- 将获取的数据按照A-Z字母开头排序
- 配置插件
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// 引入插件
import BScroll from "better-scroll";
import API from "@/api/";
export default {
data() {
return {
groupcity: {}, // 所有城市列表
scrolly: 0, // 记录滑动位置
listHeight: [], // 存储滑动高度总表
letters: [] // 记录所有城市的字母(右边框)
};
},
mounted() {
// 获取所有城市的数据
API.cityGroup().then(res => {
this.groupcity = res;
// 获取数据后开启滚动
this.$nextTick(() => {
this._initScroll();
this._calculateHeight();
});
});
}
computed: {
//将获取的数据按照A-Z字母开头排序
sortgroupcity() {
let sortobj = {};
var letters = [];
for (let i = 65; i <= 90; i++) {
if (this.groupcity[String.fromCharCode(i)]) {
sortobj[String.fromCharCode(i)] = this.groupcity[
String.fromCharCode(i)
];
// 添加城市字母
letters.push(String.fromCharCode(i));
}
}
// 动态设置到data
this.$set(this, "letters", letters);
// 返回排序好的城市数据
return sortobj;
},
// 监听滚动改变选中的侧边栏位置
currentIndex() {
for (let i = 0; i < this.listHeight.length; i++) {
const height1 = this.listHeight[i];
const height2 = this.listHeight[i + 1];
if (!height2 || (this.scrolly >= height1 && this.scrolly < height2)) {
return i;
}
}
return 0;
}
},
methods: {
/**
* 点击侧边栏改变左侧移动位置
* @param 当前选中的字母位置
* */
selectMenu(i) {
// 获取左侧城市li
let foodList = this.$refs.foodsWrapper.getElementsByClassName(
"food-list-hook"
);
// 选取相应的位置
let el = foodList[i];
// 滚动到当前
this.foodsScroll.scrollToElement(el, 300);
},
// 初始化滚动
_initScroll() {
this.meunScroll = new BScroll(this.$refs.menuWrapper, { click: true });
this.foodsScroll = new BScroll(this.$refs.foodsWrapper, {
click: true,
probeType: 3
});
this.foodsScroll.on("scroll", pos => {
console.log(this.foodsScroll);
this.scrolly = Math.abs(Math.round(pos.y));
});
},
// 记录所有滚动的高度数据
_calculateHeight() {
let foodList = this.$refs.foodsWrapper.getElementsByClassName(
"food-list-hook"
);
let height = 0;
this.listHeight.push(height);
for (let i = 0; i < foodList.length; i++) {
const item = foodList[i];
height += item.clientHeight;
this.listHeight.push(height);
}
}
}
}
4. 查验是否配置成功(把项目跑起来)
- 查验是否挂载了滚动
- 检查bs参数
后记
- vue 左右滚动联动,就说到这了还有其他的问题欢迎添加好友详聊
- 欢迎进入我的博客:https://yhf7.github.io/ 或 https://yhf7.top
- 如果有什么侵权的话,请及时添加小编微信以及 qq 也可以来告诉小编(905477376 微信 qq 通用),谢谢!