当前位置:   article > 正文

Vue/vant第左右联动better-scroll效果实现(完整版)_vant 引用better-scroll

vant 引用better-scroll

先看完整代码: 

  1. <template>
  2. <div>
  3. <!-- 头部 -->
  4. <van-sticky :offset-top="0">
  5. <div class="header">
  6. <van-icon name="chat-o" class="icon-one" />
  7. <van-search
  8. @click="search"
  9. placeholder="请输入搜索关键词"
  10. class="sousuo"
  11. />
  12. <van-icon name="scan" class="icon-two" />
  13. </div>
  14. </van-sticky>
  15. <!-- section部分 -->
  16. <section class="section" ref="sec">
  17. <div class="left" ref="left">
  18. <ul class="ulone">
  19. <li
  20. class="lione"
  21. v-for="(item, index) in leftList"
  22. :class="{ lis_one_color: index == currentIndex }"
  23. :key="index"
  24. @click="leftClick(index)"
  25. >
  26. {{ item.name }}
  27. </li>
  28. </ul>
  29. </div>
  30. <div class="right" ref="right">
  31. <ul class="rightulone">
  32. <li class="lis" v-for="(i, ind) in rightList" :key="ind">
  33. <div
  34. v-for="(item, index) in i.app_category_items"
  35. class="rightdiv"
  36. :key="index"
  37. >
  38. <div class="rightdivtwo">
  39. <div class="img">
  40. <van-image :src="item.cover" />
  41. </div>
  42. <p>{{ item.name }}</p>
  43. </div>
  44. </div>
  45. </li>
  46. </ul>
  47. </div>
  48. </section>
  49. <!-- 底部 -->
  50. <tabbbar></tabbbar>
  51. </div>
  52. </template>
  53. <script>
  54. import BetterScroll from "better-scroll";
  55. import Tabbbar from "../components/tabbbar.vue";
  56. export default {
  57. name: "VantClassification",
  58. components: {
  59. Tabbbar,
  60. },
  61. data() {
  62. return {
  63. list: [],
  64. leftList: [],
  65. rightList: [],
  66. currentIndex: 0,
  67. img: [],
  68. rightBScroll: "",
  69. leftBScroll: "",
  70. allHeight: [], //承载右侧每一块高度值
  71. flag: false,
  72. };
  73. },
  74. created() {},
  75. updated() {
  76. if (!this.rightBScroll) {
  77. this.$nextTick(() => {
  78. this.leftBScroll = new BetterScroll(this.$refs.left, {
  79. click: true,
  80. probeType: 3,
  81. });
  82. console.log(this.leftBScroll);
  83. this.rightBScroll = new BetterScroll(this.$refs.right, {
  84. probeType: 3, // 是否会截流scroll事件
  85. click: true, // 是否开启点击事件
  86. // scrollY: true, // 是否开启Y轴滚动方向
  87. // useTransition: false, // 防止iphone微信滑动卡顿
  88. // bounce: true, // 是否启用回弹动画效果
  89. // momentumLimitDistance: 5, // 符合惯性拖动的最小拖动距离
  90. });
  91. // console.log(this.rightBScroll);
  92. let height = 0;
  93. this.allHeight.push(height); // 先把0放在数组的开头
  94. let uls = this.$refs.right.getElementsByClassName("lis");
  95. Array.from(uls).forEach((v) => {
  96. height += v.clientHeight;
  97. this.allHeight.push(height); // 把每个li的高度放在新数组中
  98. // console.log(this.allHeight);
  99. });
  100. // 右侧滚动距离
  101. this.rightBScroll.on("scroll", (pos) => {
  102. this.scrollY = Math.abs(Math.round(pos.y));
  103. // console.log(this.scrollY);
  104. for (let i = 0; i < this.allHeight.length; i++) {
  105. if (
  106. this.scrollY > this.allHeight[i] &&
  107. this.scrollY < this.allHeight[i + 1]
  108. ) {
  109. if (!this.flag) {
  110. this.currentIndex = i;
  111. console.log(this.currentIndex);
  112. }
  113. }
  114. }
  115. });
  116. // 结束时距离
  117. this.rightBScroll.on("scrollEnd", (pos) => {
  118. //结束时触发事件获取一次位置,因为使用了模式2,惯性滚动不触发事件
  119. this.scrollY = Math.abs(Math.round(pos.y));
  120. this.flag = false;
  121. });
  122. });
  123. }
  124. },
  125. mounted() {
  126. let a = this.$refs.sec;
  127. a.style.height = document.documentElement.clientHeight - 95 + "px";
  128. this.getData();
  129. },
  130. computed: {},
  131. methods: {
  132. search() {
  133. this.$router.push("/search");
  134. },
  135. // 请求数据
  136. getData() {
  137. this.$axios.get("/category/app_category").then((res) => {
  138. console.log(res);
  139. this.list = res.data.data;
  140. // console.log(this.list);
  141. let leftArr = [];
  142. let rightArr = [];
  143. this.list.forEach((v) => {
  144. leftArr.push({
  145. id: v.id,
  146. name: v.name,
  147. });
  148. rightArr.push(v);
  149. /* console.log(leftArr);
  150. console.log(rightArr); */
  151. });
  152. this.leftList = leftArr;
  153. // console.log(this.leftList);
  154. // 右侧部分
  155. this.rightList = rightArr;
  156. // console.log(this.rightList);
  157. });
  158. },
  159. leftClick(index) {
  160. // console.log(index);
  161. this.flag = true;
  162. this.currentIndex = index;
  163. this.rightBScroll.scrollTo(0, -this.allHeight[index], 300);
  164. // console.log(this.allHeight[index]);
  165. },
  166. },
  167. };
  168. </script>
  169. <style scoped>
  170. .header {
  171. background-color: #fff;
  172. width: 100%;
  173. height: 45px;
  174. display: flex;
  175. justify-content: space-between;
  176. align-items: center;
  177. }
  178. .icon-one {
  179. margin-left: 0.133333rem;
  180. /* width: 7%; */
  181. }
  182. .sousuo {
  183. width: 86%;
  184. height: 45px;
  185. }
  186. .icon-two {
  187. width: 7%;
  188. margin-left: 0.133333rem;
  189. }
  190. /* section样式 */
  191. .section {
  192. margin-bottom: 50px;
  193. display: flex;
  194. overflow: hidden;
  195. }
  196. .ulone {
  197. width: 2.6667rem;
  198. overflow: hidden;
  199. }
  200. .lione {
  201. font-weight: bold;
  202. text-align: center;
  203. font-size: 18px;
  204. /* width: 100%; */
  205. height: 50px;
  206. line-height: 36px;
  207. margin: 10px 0;
  208. padding: 7px 0;
  209. box-sizing: border-box;
  210. }
  211. .lis_one_color {
  212. color: rgb(255, 102, 0);
  213. border-left: 3px rgb(255, 102, 0) solid;
  214. }
  215. .right {
  216. width: 7.3333rem;
  217. overflow: hidden;
  218. }
  219. .rightulone {
  220. width: 100%;
  221. }
  222. .rightdiv {
  223. width: 33%;
  224. /* height: 100px; */
  225. /* background-color: blue; */
  226. display: inline-block;
  227. }
  228. .img {
  229. width: 100%;
  230. height: 80px;
  231. }
  232. .rightdivtwo {
  233. width: 100%;
  234. padding: 0 5px;
  235. box-sizing: border-box;
  236. text-align: center;
  237. }
  238. </style>

主要绕一点的也就是中间的布局,之前是左右两边使用overflow:auto去写的

这里使用overflow:hidden

基本结构布局如下:

  1. <section class="section" ref="sec">
  2. <div class="left" ref="left">
  3. <ul class="ulone">
  4. <li class="lione">
  5. </li>
  6. </ul>
  7. </div>
  8. <div class="right" ref="right">
  9. <ul class="rightulone">
  10. <li>
  11. <div class="rightdiv">
  12. <div class="rightdivtwo">
  13. <div class="img">
  14. <van-image :src="item.cover" />
  15. </div>
  16. <p></p>
  17. </div>
  18. </div>
  19. </li>
  20. </ul>
  21. </div>
  22. </section>

css样式: 

  1. /* section样式 */
  2. .section {
  3. margin-bottom: 50px;
  4. display: flex;
  5. overflow: hidden;
  6. }
  7. .ulone {
  8. width: 2.6667rem;
  9. overflow: hidden;
  10. }
  11. .lione {
  12. font-weight: bold;
  13. text-align: center;
  14. font-size: 18px;
  15. /* width: 100%; */
  16. height: 50px;
  17. line-height: 36px;
  18. margin: 10px 0;
  19. padding: 7px 0;
  20. box-sizing: border-box;
  21. }
  22. .lis_one_color {
  23. color: rgb(255, 102, 0);
  24. border-left: 3px rgb(255, 102, 0) solid;
  25. }
  26. .right {
  27. width: 7.3333rem;
  28. overflow: hidden;
  29. }
  30. .rightulone {
  31. width: 100%;
  32. }
  33. .rightdiv {
  34. width: 33%;
  35. /* height: 100px; */
  36. /* background-color: blue; */
  37. display: inline-block;
  38. }
  39. .img{
  40. width: 100%;
  41. height: 80px;
  42. }
  43. .rightdivtwo {
  44. width: 100%;
  45. padding:0 5px;
  46. box-sizing: border-box;
  47. text-align: center;
  48. }

使用better-scroll插件让布局可以滚动

  1. if (!this.rightBScroll) {
  2. updated () {
  3. this.$nextTick(() => {
  4. this.leftBScroll = new BetterScroll(this.$refs.left, {
  5. click: true,
  6. probeType: 3,
  7. });
  8. console.log(this.leftBScroll);
  9. this.rightBScroll = new BetterScroll(this.$refs.right, {
  10. probeType: 3, // 是否会截流scroll事件
  11. click: true, // 是否开启点击事件
  12. // scrollY: true, // 是否开启Y轴滚动方向
  13. // useTransition: false, // 防止iphone微信滑动卡顿
  14. // bounce: true, // 是否启用回弹动画效果
  15. // momentumLimitDistance: 5, // 符合惯性拖动的最小拖动距离
  16. });
  17. console.log(this.rightBScroll);
  18. });
  19. },
  20. }

之后获取最外层的循环的六个li

  1. let height = 0;
  2. this.allHeight.push(height);// 先把0放在数组的开头
  3. let uls = this.$refs.right.getElementsByClassName('lis');
  4. Array.from(uls).forEach(v => {
  5. height += v.clientHeight
  6. this.allHeight.push(height) // 把每个li的高度放在新数组中
  7. // console.log(this.allHeight);
  8. })

核心部分

  1. if (!this.rightBScroll) {
  2. this.$nextTick(() => {
  3. this.leftBScroll = new BetterScroll(this.$refs.left, {
  4. click: true,
  5. probeType: 3,
  6. });
  7. console.log(this.leftBScroll);
  8. this.rightBScroll = new BetterScroll(this.$refs.right, {
  9. probeType: 3, // 是否会截流scroll事件
  10. click: true, // 是否开启点击事件
  11. });
  12. let height = 0;
  13. this.allHeight.push(height); // 先把0放在数组的开头
  14. let uls = this.$refs.right.getElementsByClassName("lis");
  15. Array.from(uls).forEach((v) => {
  16. height += v.clientHeight;
  17. this.allHeight.push(height); // 把每个li的高度放在新数组中
  18. });
  19. // 右侧滚动距离
  20. this.rightBScroll.on("scroll", (pos) => {
  21. this.scrollY = Math.abs(Math.round(pos.y));
  22. // console.log(this.scrollY);
  23. for (let i = 0; i < this.allHeight.length; i++) {
  24. if (
  25. this.scrollY > this.allHeight[i] &&
  26. this.scrollY < this.allHeight[i + 1]
  27. ) {
  28. if (!this.flag) {
  29. this.currentIndex = i;
  30. console.log(this.currentIndex);
  31. }
  32. }
  33. }
  34. });
  35. // 结束滚动时距离
  36. this.rightBScroll.on("scrollEnd", (pos) => {
  37. this.scrollY = Math.abs(Math.round(pos.y));
  38. this.flag = false;
  39. });
  40. });
  41. }

 

 为什么要加一个flag的状态?如果不加状态,会出现一个小bug。左边的点击事件会随着右边的滚动事件一起进行。也就是当我点击按钮让右边滚动时,左边的列表项会从上往下依次滚动到指定位置,加了这个状态后就完美的解决了冲突问题

修改前:

 修改后:

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/325808
推荐阅读
相关标签