使用Vant框架list组件遇到的坑及解决

目录
  • 使用Vant框架list组件的坑
    • 介绍
    • 特性
    • 聊一下使用list组件遇到的坑
  • vant中van-list的使用

使用Vant框架list组件的坑

介绍

Vant 是有赞前端团队开源的移动端组件库,于 2017 年开源,已持续维护 4 年时间。

Vant 对内承载了有赞所有核心业务,对外服务十多万开发者,是业界主流的移动端组件库之一。

特性

  • 提供 60 多个高质量组件,覆盖移动端各类场景
  • 性能极佳,组件平均体积不到 1kb(min+gzip)
  • 单元测试覆盖率 90%+,提供稳定性保障
  • 完善的中英文文档和示例
  • 支持 Vue 2 & Vue 3
  • 支持按需引入
  • 支持主题定制
  • 支持国际化
  • 支持 TypeScript
  • 支持 SSR

快速配置和具体介绍请去官方文档,Vant框架在Github上点赞众多,用起来发现还是很好用的,强力推荐

官方文档:https://vant-contrib.gitee.io/vant/#/zh-CN/home

聊一下使用list组件遇到的坑

官方文档的实例代码是这样的:

<van-list
  v-model="loading"
  :finished="finished"
  finished-text="没有更多了"
  @load="onLoad"
>
  <van-cell v-for="item in list" :key="item" :title="item" />
</van-list>
export default {
  data() {
    return {
      list: [],
      loading: false,
      finished: false,
    };
  },
  methods: {
    onLoad() {
      // 异步更新数据
      // setTimeout 仅做示例,真实场景中一般为 ajax 请求
      setTimeout(() => {
        for (let i = 0; i < 10; i++) {
          this.list.push(this.list.length + 1);
        }
        // 加载状态结束
        this.loading = false;
        // 数据全部加载完成
        if (this.list.length >= 40) {
          this.finished = true;
        }
      }, 1000);
    },
  },
};

效果图片:

可是!你复制代码,发现,发现完全不好用!这个定时任务简直看不懂,触底加载简直毫无逻辑,通过几个小时的研究,发现问题所在居然是CSS!对,你没有听错!是CSS导致的!

下方代码,重点看css部分,JS部分,记住settimeout不要去掉,不要相信他的注释,业务写在settimeout里就可以了

解释一下这个css的含义,就是van-list需要给他定义一个高度,并且滚动自适应,这样在不填满高度或者是滚动触底的时候就可以完美的触发onLoad时间了,这里还有一个重点!就是van-list的父级也要定义一下高度,不然也是不行的!

至于业务一定要在settimeout中写业务才能有效,了解的大佬看到了帮忙解释一下,不是很明白

<div class="txtc" style="height: 100%; position: fixed; width: 100%">
	<van-list style="height:100%;width:100%;overflow-y:auto;"
	        v-model="loading"
	        :finished="finished"
	        finished-text="没有更多了"
	        @load="onLoad"
	      >
	        <div class="divinfo" v-for="item in tableData" :key="item.sid"></div>
	</van-list>
</div>

vant中van-list的使用

van-list里面的元素不能有float样式,否则会连续触发 load 事件

原代码

<template>
  <div class="about">
    <van-tabs v-model="active" sticky @change="getTypeDate">
      <van-tab v-for="(tab) in typeList" :title="tab.name" :key="tab.id">
        <div :style="{height: contentHeight}" class="pic-content">
          <van-list
            :finished="finished"
            :finished-text="finishedText"
            v-model="loading"
            :offset="10"
            :immediate-check="false"
            @load="getserviceList"
          >
          <!------------------------------------------------- 修改前代码 --------------------------------------------->
              /*<div
                class="pic-box"
                v-for="(serve) in serviceList"
                :key="serve.id"
                @click="router(serve)"
              >
                <div class="pic-item">
                  <img
                    v-if="serve.picturePath"
                    :src="$BASE_PICTUREPATH_URL + serve.picturePath.split(',')[0]"
                  >
                </div>
                <p>{{serve.name}}</p>
                <p class="price-red">¥{{serve.price}}</p>
              </div>*/
              <!------------------------------------------------- 修改前代码 --------------------------------------------->
          </van-list>
        </div>
      </van-tab>
    </van-tabs>
  </div>
</template>
<script>
import { Tab, Tabs, List, Cell, Row, Col } from "vant";
import { FetchServeType, FetchServeList } from "../apis/serve.js";
export default {
  data() {
    return {
      active: 0,
      typeList: [],
      serviceList: [],
      type: "",
      finishedText: "",
      finished: false,
      pageNum: 1,
      pageSize: 10,
      contentHeight: 0,
      loading: false
    };
  },
  mounted() {
    this.getOrderStyle();
    this.contentHeight = document.documentElement.clientHeight - 66 - 40 + "px";
  },
  methods: {
    async getOrderStyle() {
      let res = await FetchServeType();
      if (res.data && res.data.success) {
        this.typeList = res.data.data;
        this.type = res.data.data[0].name;
        this.getTypeDate();
      }
    },
    getTypeDate() {
      this.pageNum = 1;
      this.type = this.typeList[this.active].name;
      this.serviceList = [];
      this.finishedText = "";
      this.finished = false;
      this.getserviceList();
    },
    async getserviceList() {
      let toast = this.$toast.loading({
        mask: true,
        message: "加载中..."
      });
      const { type, pageNum, pageSize } = this;
      let params = {
        type,
        pageNum,
        pageSize
      };
      let res = await FetchServeList(params);
      this.loading = false;
      toast.close();
      if (res.data && res.data.success) {
        let list = (res.data.data && res.data.data.list) || [];
        if (pageNum > 1) {
          this.serviceList = [...this.serviceList, ...list];
        } else {
          this.serviceList = list;
        }
        // 如果当前页数 = 总页数,则已经没有数据
        if (res.data.data.pageNum === res.data.data.pages) {
          this.finished = true;
          this.finishedText = "- 没有更多了-";
        }
        // 如果总页数大于当前页码,页码+1
        if (res.data.data.pages > pageNum) {
          this.pageNum++;
        }
      }
      console.log("FetchServeList: ", this.serviceList);
    }
  }
};
</script>
<style lang="scss" scoped>
.pic-content {
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
  .pic-box {
  /****************************修改前代码***************************/
    background-color: #fff;
    overflow: hidden;
    break-inside: avoid;
    box-sizing: border-box;
    margin-bottom: 0.7rem;
    padding: 0.8rem;
    width: 48%;
    height: 16rem;
    ~~float: left;~~ /**************不能有float样式*************/
    margin: 1%;
    border-radius: 4px;
     /****************************修改前代码***************************/
    p:nth-of-type(1) {
      padding: 0.8rem 0;
    }
    p:nth-of-type(2) {
      color: red;
    }
    .pic-item {
      height: 11rem;
      flex-direction: column;
      justify-content: center;
      overflow: hidden;
      img {
        width: 100%;
        height: auto;
        border-radius: 4px;
      }
    }
  }
}
</style>

// 修改后代码(注释部分为修改后代码)

<template>
  <div class="about">
    <van-tabs v-model="active" sticky @change="getTypeDate">
      <van-tab v-for="(tab) in typeList" :title="tab.name" :key="tab.id">
        <div :style="{height: contentHeight}" class="pic-content">
          <van-list
            :finished="finished"
            :finished-text="finishedText"
            v-model="loading"
            :offset="10"
            :immediate-check="false"
            @load="getserviceList"
          >
          <!------------------------------------------------- 修改后代码 --------------------------------------------->
            /*<van-row>
              <van-col
                span="12"
                class="pic-box"
                v-for="(serve) in serviceList"
                :key="serve.id"
                @click="router(serve)"
              >
                <div class="pic-item">
                  <img
                    v-if="serve.picturePath"
                    :src="$BASE_PICTUREPATH_URL + serve.picturePath.split(',')[0]"
                  >
                </div>
                <p>{{serve.name}}</p>
                <p class="price-red">¥{{serve.price}}</p>
              </van-col>
            </van-row>*/
            <!------------------------------------------------- 修改后代码 --------------------------------------------->
          </van-list>
        </div>
      </van-tab>
    </van-tabs>
  </div>
</template>
<script>
import { Tab, Tabs, List, Cell, Row, Col } from "vant";
import { FetchServeType, FetchServeList } from "../apis/serve.js";
export default {
  data() {
    return {
      active: 0,
      typeList: [],
      serviceList: [],
      type: "",
      finishedText: "",
      finished: false,
      pageNum: 1,
      pageSize: 10,
      contentHeight: 0,
      loading: false
    };
  },
  mounted() {
    this.getOrderStyle();
    this.contentHeight = document.documentElement.clientHeight - 66 - 40 + "px";
  },
  methods: {
    async getOrderStyle() {
      let res = await FetchServeType();
      if (res.data && res.data.success) {
        this.typeList = res.data.data;
        this.type = res.data.data[0].name;
        this.getTypeDate();
      }
    },
    getTypeDate() {
      this.pageNum = 1;
      this.type = this.typeList[this.active].name;
      this.serviceList = [];
      this.finishedText = "";
      this.finished = false;
      this.getserviceList();
    },
    async getserviceList() {
      let toast = this.$toast.loading({
        mask: true,
        message: "加载中..."
      });
      const { type, pageNum, pageSize } = this;
      let params = {
        type,
        pageNum,
        pageSize
      };
      let res = await FetchServeList(params);
      this.loading = false;
      toast.close();
      if (res.data && res.data.success) {
        let list = (res.data.data && res.data.data.list) || [];
        if (pageNum > 1) {
          this.serviceList = [...this.serviceList, ...list];
        } else {
          this.serviceList = list;
        }
        // 如果当前页数 = 总页数,则已经没有数据
        if (res.data.data.pageNum === res.data.data.pages) {
          this.finished = true;
          this.finishedText = "- 没有更多了-";
        }
        // 如果总页数大于当前页码,页码+1
        if (res.data.data.pages > pageNum) {
          this.pageNum++;
        }
      }
      console.log("FetchServeList: ", this.serviceList);
    }
  }
};
</script>
<style lang="scss" scoped>
.pic-content {
  overflow-y: scroll;
  -webkit-overflow-scrolling: touch;
  .pic-box {
  /************************ 修改后代码**************************/
   background-color: #fff;
    overflow: hidden;
    box-sizing: border-box;
    margin-bottom: 0.7rem;
    padding: 0.8rem;
    height: 16rem;
    border-radius: 4px;
    /************************ 修改后代码************************ **/
    p:nth-of-type(1) {
      padding: 0.8rem 0;
    }
    p:nth-of-type(2) {
      color: red;
    }
    .pic-item {
      height: 11rem;
      flex-direction: column;
      justify-content: center;
      overflow: hidden;
      img {
        width: 100%;
        height: auto;
        border-radius: 4px;
      }
    }
  }
}
</style>

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • vant list组件滚动保留滚动条位置

    vant list组件滚动保留滚动条位置,需结合keepAlive使用,分享此篇,供大家参考. 1.保存位置的前提是用的keepAlive组件来做缓存,app.vue代码 <template> <div id="app"> <keep-alive> <router-view v-if='$route.meta.keepAlive'/> </keep-alive> <router-view v-if='!$route.me

  • vue vantUI tab切换时 list组件不触发load事件的问题及解决方法

    最近由于公司项目需要,用vue写了几个简单的页面.用到了vantUI List 列表 瀑布流滚动加载,用于控制长列表的展示 当列表即将滚动到底部时,会触发事件并加载更多列表项. (页面加载完成后默认会自动加载一次,可以:immediate-check="false" 这样设置一下,页面加载完成后就不会自动加载一次了 ) 看上去一切都很美好:但是tab进行切换的时候,list组件的load事件不会再次被触发!!!就是list组件做上拉加载只有在第一个tab会触发,切换后触底不会再次触发

  • 解决vant框架做H5时踩过的坑(下拉刷新、上拉加载等)

    1. 页面在手机端不能上下滑动,在PC端浏览器正常滑动 说明:在设置了overflow:auto;属性的前提下,H5页面在PC端浏览器里展示可以上下滑动,在ios上可正常滑动,在安卓手机 上不能上下滑动:这现象并不是ios和安卓兼容性问题! 原因:设置了touch-action: none;这属性为局部或者全局属性,将这条属性注释即可正常滑动. 2.使用PullRefresh和List列表实现下拉刷新和上拉加载时出现的问题 问题1. 下拉刷新时在手机上,不论滑到任何位置,只要下拉就刷新 原因:滑

  • vant 中van-list的用法说明

    van-list里面的元素不能有float样式,否则会连续触发 load 事件 原代码 <template> <div class="about"> <van-tabs v-model="active" sticky @change="getTypeDate"> <van-tab v-for="(tab) in typeList" :title="tab.name"

  • vant-ui框架的一个bug(解决切换后onload不触发)

    前几天做的项目里有用到下拉刷新.使用了vant-ui里的 List 列表 瀑布流滚动加载,用于控制长列表的展示 先说使用 1.用npm下载该模块包 npm i vant -S 2.引入组件 官方提供了三种方法.(我使用了第三种,全局引入方法) 方式一. 使用 babel-plugin-import(推荐) babel-plugin-import 是一款 babel 插件,它会在编译过程中将 import 的写法自动转换为按需引入的方式 # 安装 babel-plugin-import 插件 np

  • 使用Vant框架list组件遇到的坑及解决

    目录 使用Vant框架list组件的坑 介绍 特性 聊一下使用list组件遇到的坑 vant中van-list的使用 使用Vant框架list组件的坑 介绍 Vant 是有赞前端团队开源的移动端组件库,于 2017 年开源,已持续维护 4 年时间. Vant 对内承载了有赞所有核心业务,对外服务十多万开发者,是业界主流的移动端组件库之一. 特性 提供 60 多个高质量组件,覆盖移动端各类场景 性能极佳,组件平均体积不到 1kb(min+gzip) 单元测试覆盖率 90%+,提供稳定性保障 完善的

  • Vant中List组件immediate-check=false无效的解决

    目录 Vant中List组件immediate-check=false无效 问题场景 解决方法 Vant list组件使用的坑 总结 Vant中List组件immediate-check=false无效 使用vant中的List组件时,会有这样的场景 初始化时想自己触发列表查询,而不想触发 List 组件自带的 load 方法,这时可以设置 immediate-check=false,如下代码,但是这种方式会在下面的场景中出现问题 <van-list ref="vanlist"

  • 解决vant中 tab栏遇到的坑 van-tabs

    话不多说,先看下问题描述: 我的需求:(和头条的tab栏类似 ,单击查看头条tab栏) 点击tab栏,下方展示出来当前tab栏下的内容列表(A页面),点击列表进入详情内容(B页面),但是返回(A页面)的时候,需要显示刚才被点击的tab栏高亮显示.(如果tab栏横向有滚动条,那也得让被选中的高亮显示). 所以,大部分人的解决办法就是将当前选中的tab的索引缓存起来,等回到该页面的时候,让被缓存的那个高亮显示出来. 坑的问题在于:van-tabs,里面的v-model默认值是0,但是类型却写着 nu

  • 解决vue加scoped后就无法修改vant的UI组件的样式问题

    有时候UI组件提供的默认的样式不能满足项目的需要,就需要我们对它的样式进行修改,但是发现加了scoped后修改的样式不起作用. 解决方法: 使用深度选择器,将scoped样式中的选择器"深入",即影响子组件 <style scoped> .a >>> .b { /* ... */ } </style> 以上的代码会编译成: .a[data-v-f3f3eg9] .b { /* ... */ } 注意:如果你使用了Less或Sass等预处理器,可

  • 解决vant的Toast组件时提示not defined的问题

    按照官方文档引入全局Toast组件,在methods里面定义函数执行函数时产生了报错: //定义的函数 handleClick(){ Toast('点击提示') } 报错信息 [Vue warn]: Error in v-on handler: "ReferenceError: Toast is not defined" 解决方法: handleClick(){ this.$toast('点击提示') } 补充知识:vue+vant移动端遇到的那些问题 1.项目引用了lib-flexi

  • 微信小程序引入Vant框架的全过程记录

    前言 有时候会觉得微信小程序原生的ui差了那么一点点感觉,那么能不能引入三方框架呢?本文以引入Vant来进行举例,共包含8个步骤.不管是不是云开发项目都一样使用. 实现步骤 1. 打开微信小程序的开发工具,进入项目.在项目的根目录文件上点击右键.选择在终端中打开.(注意是根目录) 2. 在命令窗口中键入npm init.然后所有配置都按默认配置进行,只需点击回车键即可. 3. 在命令窗口中键入npm install进行构建,成功之后会在根目录下生成 package.json 和 package-

  • 微信小程序中使用vant框架的具体步骤

    目录 1.打开我们小程序的项目目录,然后打开文件所在的位置. 2.初始化项目文件 3.输入初始化项目的命令 4.安装依赖 5.使用组件 1.说到vant框架相信大家应该并不陌生了吧,做过移动端开发的小伙伴们应该都知道它吧. 2.Vant 是有赞前端团队开源的移动端组件库,于 2017 年开源,已持续维护 4 年时间.Vant 对内承载了有赞所有核心业务,对外服务十多万开发者,是业界主流的移动端组件库之一. 3.我们废话不多说,直接进入今天的主题.我们该如何在微信小程序中去使用vant组件库呢!

  • Python Web框架之Django框架Form组件用法详解

    本文实例讲述了Python Web框架之Django框架Form组件用法.分享给大家供大家参考,具体如下: Form简介 在HTTP中,表单(form标签),是用来提交数据的,其action属性说明了其传输数据的方法:如何传.如何接收. 访问网站时,表单可以实现客户端与服务器之间的通信.例如查询,就用到了表单(其属性中,action=get). 再比如说注册与登陆,也是要用到表单的.但这里由于涉及到隐私问题,需要保证数据传输的安全性,因此其传输方法就应当使用post而非get. 总之,对客户端来

  • Yii框架响应组件用法实例分析

    本文实例讲述了Yii框架响应组件用法.分享给大家供大家参考,具体如下: 当我们的浏览器发送过来一个请求之后,在我们的操作里面对请求经过处理之后,我们的服务器也会把请求的结果打包成一个消息,然后把这个消息返还给浏览器,这个消息我们称之为响应.在我们的操作中,我们也可以对响应进行一些设置和处理.要处理我们的响应,我们需要先获得响应组件这个东西. $response = \Yii::$app->response; 有了这个响应组件之后,我们可以对响应消息进行一些设置了,比如设置响应的状态码. $res

随机推荐