实战技巧、vue+vant开发移动端

2,922 阅读5分钟

section A 移动端适配方案

Vue移动端h5适配解决方案(lib-flexible+px2rem-loader)

  1. px2rem-loader:将css中的px转为rem单位,用了它就不用自己计算rem值了
  2. lib-flexible:根据设备宽度,修改根元素html的font-size,以适配不同终端

配置

  • 安装1:npm i px2rem-loader --save -dev
  • 安装2:npm i lib-flexible --save
  • 配置1:入口文件main.js中引入:import 'lib-flexible/flexible.js'
  • 配置2:vue.config.js里面
css: {
    loaderOptions: {
        css: {
            // options here will be passed to css-loader
        },
        postcss: {
            // options here will be passed to postcss-loader
            plugins: [require('postcss-px2rem')({
                remUnit: 37.5 //说明1rem为37.5px,根据设计稿来定一般为750,我这个是375
            })]
        }
    }

友情提示:行内样式是无法转化rem的

section B 项目过程中遇到的问题

UI库使用的是vant,虽然没用过感觉UI库基本都是一样的,很容易上手

one A 下拉刷新+加载更多

先看下效果图 移动端下拉刷新、加载更多还是比较常见的 整个页面列表相对简单、局部列表就有点麻烦了,下拉刷新+加载更多结合体还是需要结合场景做出相应改变的,生搬硬套是不行的。(文章最后会给出完整代码

就以20条数据为一页,下拉加载更多为例 由于一个页面可切换列表切都具备加载更多、下拉刷新功能,同一个组件在一个页面使用多次,担心会互相影响,咱们可以这么写

const detailGold = () => import('./components/detail');
const detailMoney = () => import('./components/detail');

(父组件)动态给与外层盒子高度适配各种手机

<div
class="list-content"
ref="listbox"
:style="'height:' + listheight + 'px'"
>
<detail-gold
@childMsg="childMsg"
:list="listGold"
v-if="gold"
:finishList="finishList"
></detail-gold>
<detail-money
@childMsg="childMsg"
:list="listMoney"
v-if="money"
:finishList="finishList"
></detail-money>
</div>
data() {
    return {
      // 动态获取页面  
      clientHeight: window.screen.height,
      listheight: '',
      // 子组件传参
      listGold: [],
      listMoney: [],
      // 下一页
      lastindicateGold: '',
      lastindicateCash: '',
      //判断tab切换
      gold: true,
      money: false,
      //计时器
      timer: null,
      //刚刚好20条数据,下次请求无数据,避免一直loading
      finishList: true
    }
},
created() {
    let id = this.$route.query.id;
    if (id == 1) {
      this.isactive = true;
      this.subtitle = '金币收益';
      this.company = '(个)';
      this.gold = true;
      this.money = false;
    } else if (id == 2) {
      this.isactive = false;
      this.subtitle = '现金收益';
      this.company = '(元)';
      this.gold = false;
      this.money = true;
    }
    this.getData(id);
    // 动态获取高度
    this.$nextTick(() => {
      let top = this.$refs.listbox.offsetTop;
      this.listheight = this.clientHeight - top;
    })
  },

把列表写成一个子组件

<template>
  <div class="detail" ref="detail">
    <van-pull-refresh
      ref="detailpull"
      class="pull"
      :style="'height:' + pullH + 'px'"
      v-model="refreshing"
      @refresh="onRefresh"
    >
      <van-list
        v-model="loading"
        :offset="10"
        :finished="finished"
        finished-text="没有更多了"
        :error.sync="error"
        error-text="请求失败,点击重新加载"
        @load="onLoad"
      >
        <div class="detail-box" v-for="(item, index) in list" :key="index">
          <div class="left">
            <div class="title">{{ item.title }}</div>
            <div class="time">
              {{ item.transFullTime | timeFormat("YYYY-MM-DD HH:mm:ss") }}
            </div>
          </div>
          <div class="right">
            <div class="sybol">+</div>
            <div class="number">{{ item.number }}</div>
          </div>
        </div>
      </van-list>
    </van-pull-refresh>
  </div>
</template>

1. 进页面会触发一次onload事件,第一次如果在子组件触发的话会很慢,出现局部空白的情况,所以选择在父组件触发,看下onload

props: {
    friendsList: Array,
    finishList:Boolean
},
data() {
    return {
        loading: false,
        finished: false,
        more: 0
    }
},
mounted() {
// 切换得归零
this.more = 0
},
methods:{
//加载更多    
onLoad(refresh) {
    if (this.finishList == false && this.refreshing == false) {
    this.loading = false
    this.finished = true
    return
    }
    this.more++
    if (this.more > 1) {
    if (refresh) {
        this.$emit('childMsg', refresh)
    } else {
        this.$emit('childMsg')
    }
},
//下拉刷新
onRefresh() {
      // 清空列表数据
      this.finished = false;
      // 重新加载数据
      // 将 loading 设置为 true,表示处于加载状态
      this.loading = true;
      this.onLoad('refresh');
    },
} 

2. 下滑会多次触发onload事件,需要在父组件进行防抖处理

tip:使用定时器注意this指向问题

childMsg(msg) {
    let that = this;
    console.log(msg)
    if (!that.timer) {
    that.timer = setTimeout(() => {
        if (msg) {
        that.finishList = true
        if (that.subtitle == '金币收益') {
            that.listGold = []
            that.lastindicateGold = ''
            that.getData(1)
            that.timer = null;
            return
        } else {
            that.listMoney = []
            that.lastindicateCash = ''
            that.getData(2)
            that.timer = null;
            return
        }
        } else {
        if (that.subtitle == '金币收益') {
            if (that.lastindicateGold == '') {
            that.getData(1)
            } else {
            that.getData(1, that.lastindicateGold)
            }
        } else {
            if (that.lastindicateCash == '') {
            that.getData(2)
            } else {
            that.getData(2, that.lastindicateCash)
            }
        }
        }
        that.timer = null;
    }, 1000)
    }
},

3. 子组件中如果出现无数据情况特殊处理,下拉只能拉动局部问题,获取list高度,如果list高度小于父组件,则直接等于父组件高度就可以拉动全屏啦动态给list高度

props: {
    friendsList: Array,
    finishList:Boolean
},
data() {
    return {
        loading: false,
        finished: false,
        more: 0
    }
},
methods:{
    onLoad(refresh) {
    this.more++
    if (this.more > 1) {
    this.$emit('childMsg')
    }
},
  watch: {
    list: function (val) {
      console.log(val)
      if (this.refreshing) {
        this.refreshing = false;
        return
      }
      if (val.length < 20 || val.length % 20 > 0) {
        this.finished = true;
      }else{
        this.finished = false
      }
      this.loading = false;

    },
    //刚刚好20条数据,下次请求无数据,避免一直loading
    finishList: function (val) {
      if (val == false) {
        this.loading = false
        this.finished = true
      } else {
        this.loading = true
        this.finished = false
      }
      // 动态给下拉高度,防止无数据时出现下拉问题
      this.$nextTick(() => {
        let detailHeight = this.$refs.detail.offsetHeight;
        let pullHeight = this.$refs.detailpull.$el.offsetHeight
        console.log(detailHeight, pullHeight)
        if (pullHeight < detailHeight) {
          this.pullH = detailHeight
        }
      })
    }
  },

4. 这时候觉得OK了,仔细看看效果你会发现下拉出现两个loading效果,出现这个是因为下拉函数的问题,需要改进下

onLoad(refresh) {
      if (this.finishList == false && this.refreshing == false) {
        this.loading = false
        this.finished = true
        return
      }
      this.more++
      if (this.more > 1) {     
          this.$emit('childMsg')
      }
    },
    onRefresh() {
      this.$emit('childMsg', 'refresh')
    },

two B 移动端长按保存

利用touchstart、touchmove、touchend实现移动端长按保存 直接用代码说话吧

<template>
  <div
    class="qrcode"
    :style="'height:' + qrheight + 'px'"
    @touchstart="gotouchstart"
    @touchmove="gotouchmove"
    @touchend="gotouchend"
  >
  </div>
</template>

<script>
export default {
  data() {
    return {
      timeOutEvent: null,
    }
  },
  methods: {
    gotouchstart() {
      let that = this;
      clearTimeout(that.timeOutEvent);//清除定时器
      that.timeOutEvent = null;
      that.timeOutEvent = setTimeout(function () {
        //执行长按要执行的内容,
        
      }, 800);//这里设置定时
    },
    //手释放,如果在500毫秒内就释放,则取消长按事件,此时可以执行onclick应该执行的事件
    gotouchend() {
      let that = this;
      clearTimeout(that.timeOutEvent);
      that.timeOutEvent = null
      if (that.timeOutEvent != 0) {
        //这里写要执行的内容(尤如onclick事件)
      }
    },
    //如果手指有移动,则取消所有事件,此时说明用户只是要移动而不是长按 
    gotouchmove(e) {
      e.preventDefault()
      let that = this;
      clearTimeout(that.timeOutEvent);//清除定时器
      that.timeOutEvent = null
    },
  }
}
</script>

three C 保存二维码到手机相册

这个我真的尝试了很多方法,在浏览器可以但是放到APP中用webview打开就不行了,为什么呢?因为webview打开的页面把所有的事件都默认阻止了,这就需要安卓/IOS原生配合做下面两项工作了解惑小火车

  • webview监听网页的下载链接。
  • 使用系统的DownloadManager进行下载。

我想到两种解决方案

1. 把图片转换成二进制文件流,传给安卓/IOS

data() {
    return {
        saveImgpath: require('../../../public/img/qrcode.png')
    }
},
	image2Base64(img) {
      var canvas = document.createElement("canvas");
      let w = window.screen.width;
      let h = window.screen.height;
      canvas.width = w;
      canvas.height = h;
      var ctx = canvas.getContext("2d");
      ctx.drawImage(img, 0, 0, w, h);
      var dataURL = canvas.toDataURL("image/png");
      return dataURL;
    },
    getImgBase64(url) {//url就是saveImgpath
      let that = this
      var base64 = "";
      var img = new Image();
      img.src = url;
      img.onload = function () {
        base64 = that.image2Base64(img);
        console.log(base64);
        //传给原生
        that.$bridge.signalCommunication('saveImg',base64)
      }
    }

2. 让安卓/IOS监听网页的下载行为,给与“通行”

data() {
    return {
        saveImgpath: require('../../../public/img/qrcode.png')
    }
},
saveImg(Url) { //Url就是saveImgpath
    var blob = new Blob([''], { type: 'application/octet-stream' });
    var url = URL.createObjectURL(blob);
    var a = document.createElement('a');
    a.href = Url;
    a.download = Url.replace(/(.*\/)*([^.]+.*)/ig, "$2").split("?")[0];
    var e = document.createEvent('MouseEvents');
    e.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
    a.dispatchEvent(e);
    URL.revokeObjectURL(url);
},

section C 实用小技巧

1. data里面准备传给子组件的值必须标明类型,否则子组件无法接受会报错

2. 使用vant的Overlay 遮罩层lock-scroll这个属性是默认开启的,无法滚动背景上的任何元素,只有将其赋值false才可以滚动背景上的元素

3. 移动端阻止双击手机屏幕放大

* {
      margin: 0;
      padding: 0;
      -webkit-touch-callout: none;
      /**系统默认菜单被禁用*/
      -webkit-user-select: none;
      /**webkit浏览器*/
      -khtml-user-select: none;
      /**早期浏览器*/
      -moz-user-select: none;
      /**火狐*/
      -ms-user-select: none;
      /**IE10*/
      user-select: none;
    }
input,
    textarea {
      -webkit-user-select: auto;
    }

4. 阻止IOS双击页面上滑/下滑

<script type="text/javascript">
    var agent = navigator.userAgent.toLowerCase();
    var iLastTouch = null;
    if (agent.indexOf("iphone") >= 0 || agent.indexOf("ipad") >= 0) {
      document.body.addEventListener("touchend", function (event) {
        var a = new Date().getTime();
        iLastTouch = iLastTouch || a + 1;
        var c = a - iLastTouch;
        if (c < 500 && c > 0) {
          event.preventDefault();
          return false;
        }
        iLastTouch = a
      }, false);
    };
    document.documentElement.addEventListener('touchmove', function (event) {
      if (event.touches.length > 1) {
        event.preventDefault();
      }
    }, false);
  </script>

5. 安装/卸载依赖

npm install 模块

本地安装的时候,将依赖包信息写入package.json中

注意一个问题,在团队协作中,一个常见的情景是他人从github上clone你的项目,然后通过npm install安装必要的依赖,(刚从github上clone下来是没有node_modules的,需要安装)那么根据什么信息安装依赖呢?就是你的package.json中的dependencies和devDepencies。所以,在本地安装的同时,将依赖包的信息(要求的名称和版本)写入package.json中是很重要的!

npm install 模块:安装好后不写入package.json中

npm install 模块 --save 安装好后写入package.json的dependencies中(生产环境依赖)

npm install 模块 --save-dev 安装好后写入package.json的devDepencies中(开发环境依赖)

npm uninstall 模块

删除本地模块时你应该思考的问题:是否将在package.json上的相应依赖信息也消除?

npm uninstall 模块:删除模块,但不删除模块留在package.json中的对应信息

npm uninstall 模块 --save 删除模块,同时删除模块留在package.json中dependencies下的对应信息

npm uninstall 模块 --save-dev 删除模块,同时删除模块留在package.json中devDependencies下的对应信息

6. PC、移动端通用禁止输入汉字空格,只允许输入数字

<!-- 禁止输入汉字空格,只允许输入数字 -->
<input
class="inp"
type="text"
v-model.trim="info.account"
placeholder="请输入数字"
onkeyup="value=value.replace(/^(0+)|[^\d]+/g,'')"
/>
<!-- 禁止输入空格 -->
<input
class="inp"
type="text"
v-model.trim="info.name"
placeholder=""
onkeyup="this.value=this.value.replace(/\s+/g,'')"
/>

7. 好看的滚动条样式

.block-tips::-webkit-scrollbar {
  width: 5px;

  height: 13px;

  -webkit-border-radius: 5px;

  -moz-border-radius: 5px;

  border-radius: 5px;
}

.block-tips::-webkit-scrollbar-thumb {
  background-color: #DEDEE4;

  background-clip: padding-box;

  -webkit-border-radius: 5px;

  -moz-border-radius: 5px;

  border-radius: 5px;

  min-height: 28px;
}

附录

section B one A 下拉刷新+加载更多完整代码 父组件

<template>
  <div class="profit">
    <div class="profit-box">
      <div class="pro-box">
        <headers :header="headData"></headers>
        <div class="subtitle">
          <div class="sub">
            <span>{{ subtitle }}</span>
            <span class="company">{{ company }}</span>
          </div>
          <div class="number">{{ balance }}</div>
        </div>
      </div>
      <div class="content">
        <div class="list-header">
          <div class="pro" :class="{ active: gold }" @click="proClick(1)">
            金币收益
          </div>
          <div class="pro" :class="{ active: money }" @click="proClick(2)">
            现金收益
          </div>
        </div>
        <div
          class="list-content"
          ref="listbox"
          :style="'height:' + listheight + 'px'"
        >
          <detail-gold
            @childMsg="childMsg"
            :list="listGold"
            v-if="gold"
            :finishList="finishList"
          ></detail-gold>
          <detail-money
            @childMsg="childMsg"
            :list="listMoney"
            v-if="money"
            :finishList="finishList"
          ></detail-money>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import headers from '../../components/headers'
const detailGold = () => import('./components/detail');
const detailMoney = () => import('./components/detail');
import { incomeRecord } from '@/api/index.js'
export default {
  name: 'money',
  components: {
    headers,
    detailGold,
    detailMoney
  },
  data() {
    return {
      headData: {
        title: '我的收益',
        other: false
      },
      isGold: false,
      isMoney: false,
      isactive: true,
      subtitle: '金币收益',
      company: '(个)',
      balance: '',
      clientHeight: window.screen.height,
      listheight: '',
      listGold: [],
      listMoney: [],
      // 下一页
      lastindicateGold: '',
      lastindicateCash: '',
      gold: true,
      money: false,
      timer: null,
      //刚刚好20条数据,下次请求无数据,避免一直loading
      finishList: true
    }
  },
  created() {
    let id = this.$route.query.id;
    if (id == 1) {
      this.isactive = true;
      this.subtitle = '金币收益';
      this.company = '(个)';
      this.gold = true;
      this.money = false;
    } else if (id == 2) {
      this.isactive = false;
      this.subtitle = '现金收益';
      this.company = '(元)';
      this.gold = false;
      this.money = true;
    }
    this.getData(id);
    // 动态获取高度
    this.$nextTick(() => {
      let top = this.$refs.listbox.offsetTop;
      this.listheight = this.clientHeight - top;
    })
  },
  methods: {
    back() {
      this.$router.go(-1);//返回上一层
    },
    // 金币/现金切换
    proClick(id) {
      // this.getData (id);
      if (id == 1) {
        if (this.gold == true) {
          return
        }
        this.finishList = true
        this.subtitle = '金币收益'
        this.company = '(个)'
        this.listGold = []
        this.getData(1)
        this.gold = true
        this.money = false
      } else {
        if (this.money == true) {
          return
        }
        this.finishList = true
        this.subtitle = '现金收益'
        this.company = '(元)'
        this.listMoney = []
        this.getData(2)
        this.gold = false
        this.money = true
      }
    },
    // 获取数据
    getData(type, lastindicate) {
      let data = {};
      data.userId = this.$global.userId;
      data.type = type;
      data.limit = 20;
      if (lastindicate) {
        data.lastindicate = lastindicate;
      }
      incomeRecord(data).then(res => {
        if (type == 1) {
          this.balance = res.data.gold.toFixed(2);
        } else if (type == 2) {
          this.balance = res.data.balance.toFixed(2);
        }
        if (res.data.info.length == 0) {
          this.finishList = false
          return
        }
        // 金币收益
        if (type == 1) {
          if (this.listGold.length == 0) {
            // this.balance = res.data.gold.toFixed(2);
            this.listGold = res.data.info;
            this.listGold.map((item, i) => {
              this.listGold[i].title = this.goldType(this.listGold[i].goldType)
              this.listGold[i].number = this.listGold[i].gold
            })
          } else {
            let newArr = res.data.info
            newArr.map((item, i) => {
              newArr[i].title = this.goldType(newArr[i].goldType)
              newArr[i].number = newArr[i].gold
            })
            for (let i = 0; i < newArr.length; i++) {
              this.listGold.push(newArr[i])
            }
          }
          this.lastindicateGold = res.data.lastindicate
        } else {
          // 现金收益
          if (this.listMoney.length == 0) {
            this.balance = res.data.balance.toFixed(2);
            this.listMoney = res.data.info;
            this.listMoney.map((item, i) => {
              this.listMoney[i].title = this.cashType(this.listMoney[i].cashType)
              this.listMoney[i].number = this.listMoney[i].cash
            })
          } else {
            let newArr = res.data.info
            newArr.map((item, i) => {
              newArr[i].title = this.goldType(newArr[i].cashType)
              newArr[i].number = newArr[i].cash
            })
            for (let i = 0; i < newArr.length; i++) {
              this.listMoney.push(newArr[i])
            }
          }
          this.lastindicateCash = res.data.lastindicate
        }
      })
    },
    // 金币收益类型
    goldType(type) {
      switch (type) {
        case 1:
          return '金币兑换现金';

        case 2:
          return '好友阅读贡献';

        case 3:
          return '填写邀请码';

        case 4:
          return '阅读内容';

        case 5:
          return '优质内容';

        case 6:
          return '每日登录';

        case 7:
          return '朋友圈邀请';

        case 8:
          return '微信群邀请';

        case 9:
          return '明日之星';

        case 10:
          return '阅读奖励';

        case 11:
          return '好友贡献';

        case 12:
          return '好友贡献(名下好友)';
      }
    },
    // 现金收益类型
    cashType(type) {
      switch (type) {
        case 1:
          return '金币兑换现金'
        case 2:
          return '提现'
        case 3:
          return '首次邀请好友完成任务'
        case 4:
          return '首次邀请好友(1元立刻到帐)'
        case 5:
          return '新用户奖励'
      }
    },
    childMsg(msg) {
      let that = this;
      console.log(msg)
      if (!that.timer) {
        that.timer = setTimeout(() => {
          if (msg) {
            that.finishList = true
            if (that.subtitle == '金币收益') {
              that.listGold = []
              that.lastindicateGold = ''
              that.getData(1)
              that.timer = null;
              return
            } else {
              that.listMoney = []
              that.lastindicateCash = ''
              that.getData(2)
              that.timer = null;
              return
            }
          } else {
            if (that.subtitle == '金币收益') {
              if (that.lastindicateGold == '') {
                that.getData(1)
              } else {
                that.getData(1, that.lastindicateGold)
              }
            } else {
              if (that.lastindicateCash == '') {
                that.getData(2)
              } else {
                that.getData(2, that.lastindicateCash)
              }
            }
          }
          that.timer = null;
        }, 1000)
      }
    },
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped lang="scss">
.profit {
  .profit-box {
    background: #efeff5 100%;
    .pro-box {
      background-color: rgba(255, 255, 255, 1);
      border-radius: 0px 0px 10px 10px;
      .header {
        margin-top: 52px;
        display: flex;
        position: relative;
        padding-bottom: 12px;
        color: rgba(255, 255, 255, 0);
        font-size: 20px;
        text-align: center;
        box-shadow: 0px -1px 20px 0px rgba(245, 245, 245, 1);
        font-family: Arial;
        .return {
          margin-left: 15px;
        }
        .text {
          width: 65px;
          height: 16px;
          color: rgba(0, 0, 0, 1);
          font-size: 16px;
          text-align: center;
          font-family: Arial;
          font-weight: bold;
          position: absolute;
          left: 50%;
          top: -3px;
          transform: translateX(-50%);
          vertical-align: top;
        }
      }
      .subtitle {
        // padding-top: 12px;
        height: 90px;
        border-radius: 0px 0px 10px 10px;
        text-align: center;
        .sub {
          margin-top: 20px;
          height: 13px;
          color: rgba(0, 0, 0, 1);
          font-size: 13px;
          text-align: center;
          font-family: Arial;
          .company {
            margin-left: 3px;
          }
        }
        .number {
          margin-top: 20px;
          height: 30px;
          color: rgba(255, 0, 0, 1);
          font-size: 30px;
          text-align: center;
          font-family: Arial;
        }
      }
    }
    .content {
      background: #ffffff;
      margin-top: 10px;
      border-radius: 10px 10px 0px 0px;
      .list-header {
        border-radius: 10px 10px 0px 0px;
        height: 46px;
        border: 1px solid rgba(239, 239, 245, 1);
        box-sizing: border-box;
        display: flex;
        align-items: center;
        .pro {
          height: 16px;
          color: rgba(144, 143, 143, 1);
          font-size: 16px;
          text-align: center;
          font-family: Arial;
          width: 50%;
        }
        .active {
          height: 16px;
          color: rgba(255, 0, 0, 1);
          font-size: 16px;
          text-align: center;
          font-family: Arial;
        }
      }
      .list-content {
        // padding: 15px 15px 30px 15px;
        // height: 566px;
        overflow: auto;
      }
    }
  }
}
</style>

子组件

<template>
  <div class="detail" ref="detail">
    <van-pull-refresh
      ref="detailpull"
      class="pull"
      :style="'height:' + pullH + 'px'"
      v-model="refreshing"
      @refresh="onRefresh"
    >
      <van-list
        v-model="loading"
        :offset="10"
        :finished="finished"
        finished-text="没有更多了"
        :error.sync="error"
        error-text="请求失败,点击重新加载"
        @load="onLoad"
      >
        <div class="detail-box" v-for="(item, index) in list" :key="index">
          <div class="left">
            <div class="title">{{ item.title }}</div>
            <div class="time">
              {{ item.transFullTime | timeFormat("YYYY-MM-DD HH:mm:ss") }}
            </div>
          </div>
          <div class="right">
            <div class="sybol">+</div>
            <div class="number">{{ item.number }}</div>
          </div>
        </div>
      </van-list>
    </van-pull-refresh>
  </div>
</template>

<script>
export default {
  props: ['list', 'finishList'],
  data() {
    return {
      loading: false,
      finished: false,
      error: false,
      more: 0,
      timer: null,
      refreshing: false,
      pullH: ''
    }
  },
  mounted() {
    // this.listData = this.list
    this.more = 0
  },
  watch: {
    list: function (val) {
      console.log(val)
      if (this.refreshing) {
        this.refreshing = false;
        return
      }
      if (val.length < 20 || val.length % 20 > 0) {
        this.finished = true;
      }else{
        this.finished = false
      }
      this.loading = false;

    },
    //刚刚好20条数据,下次请求无数据,避免一直loading
    finishList: function (val) {
      if (val == false) {
        this.loading = false
        this.finished = true
      } else {
        this.loading = true
        this.finished = false
      }
      // 动态给下拉高度,防止无数据时出现下拉问题
      this.$nextTick(() => {
        let detailHeight = this.$refs.detail.offsetHeight;
        let pullHeight = this.$refs.detailpull.$el.offsetHeight
        console.log(detailHeight, pullHeight)
        if (pullHeight < detailHeight) {
          this.pullH = detailHeight
        }
      })
    }
  },
  methods: {
    onLoad(refresh) {
      if (this.finishList == false && this.refreshing == false) {
        this.loading = false
        this.finished = true
        return
      }
      this.more++
      if (this.more > 1) {
        this.$emit('childMsg')
      }
    },
    onRefresh() {
      this.$emit('childMsg', 'refresh')
    },
  }
}
</script>

<style  scoped lang='scss'>
.detail {
  height: 100%;
  .detail-box {
    padding: 0px 15px 0px 15px;
    display: flex;
    margin-top: 30px;
    .left {
      width: 50%;
      text-align: left;
      .title {
        height: 14px;
        color: rgba(0, 0, 0, 1);
        font-size: 14px;
        font-family: Arial;
      }
      .time {
        margin-top: 10px;
        height: 10px;
        line-height: 17px;
        color: rgba(144, 143, 143, 1);
        font-size: 12px;
        font-family: Arial;
      }
    }
    .right {
      width: 50%;
      color: rgba(255, 0, 0, 1);
      align-items: center;
      justify-content: flex-end;
      display: flex;
      .sybol {
        width: 13px;
        height: 28px;
        font-size: 20px;
        font-family: PingFangSC-regular;
      }
      .number {
        margin-left: 5px;
        height: 28px;
        font-size: 20px;
        text-align: left;
        font-family: PingFangSC-regular;
      }
    }
    .active {
      color: rgba(68, 139, 242, 1);
    }
  }
  .detail-box:nth-child(1) {
    margin-top: 0px;
    padding-top: 15px;
  }
}
.pull {
  background: #efeff5 !important;
}
</style>

写在最后

我是凉城a,一个前端,热爱技术也热爱生活。

与你相逢,我很开心。

如果你想了解更多,请点这里,期待你的小⭐⭐

  • 文中如有错误,欢迎在评论区指正,如果这篇文章帮到了你,欢迎点赞和关注😊

  • 本文首发于掘金,未经许可禁止转载💌