vue.js 모 바 일 앱 위 에 로드 및 드 롭 다운 리 셋 실전

위로 끌 어 올 리 거나 아래로 끌 어 올 리 는 것 은 모 바 일 에서 흔히 볼 수 있 는 기능 으로 검색 이나 분류 목록 페이지 에서 자주 사용 된다.

가로 스크롤 과 마찬가지 로 우 리 는 better-scroll 라 이브 러 리 를 사용 하여 이 루어 집 니 다.better 는 이미 새로운 버 전 을 업 데 이 트 했 기 때문에 이전 에는 0.몇 버 전 이 었 습 니 다.업 데 이 트 를 해 보 니 지금 은 1.2.6 버 전이 되 었 습 니 다.새로운 버 전 은 비교적 사용 하기 좋 은 api 가 많아 졌 습 니 다.그래서 저도 예전 의 코드 를 다시 썼 고 새로운 api 로 업로드 와 드 롭 다운 리 셋 을 실 현 했 습 니 다.
먼저 기본 적 인 스타일 을 쓰 고 여 기 는 생략 한 다음 에 better-scroll 라 이브 러 리 를 도입 합 니 다.

import BScroll from 'better-scroll'
그 다음 에 mounted 라 이 프 사이클 에서 scroll 을 예화 하면 데 이 터 를 얻 은 후에 new 를 얻 을 수 있 고 new 를 먼저 얻 은 후에 데 이 터 를 가 져 와 refresh 를 호출 할 수 있 습 니 다.
인 스 턴 스 를 사용 할 때 설정 매개 변 수 를 입력 해 야 합 니 다.매개 변수 가 비교적 많 기 때문에 구체 적 인 것 은 문 서 를 참고 하 십시오.여 기 는 두 가지 중점 만 말씀 드 리 겠 습 니 다.

//        ,   true  false,                

pullDownRefresh:{
  threshold:80,
  stop:40
}

//        ,  ,   stop  ,         
pullUpLoad:{
  threshold:-80,
}

/**
 * 
 * @param threshold        ,         
 * @param stop               (   loading      )
 */

이상 의 숫자 는 개인 적 으로 적당 하 다 고 생각 하지만 여기 서 문제 가 있 습 니 다.제 가 타 오 바 오 플 렉 시 블 제 이 스 를 사용 해서 어 울 립 니 다.그래서 안 드 로 이 드 에서 80 이라는 거 리 는 적당 하지만 아이 폰 6s 에 이 르 러 3 배 를 확대 되 었 기 때문에 현재 80 은 아이 폰 6s 에서 27 정도 입 니 다.
따라서 크기 조정 정도 가 다른 화면 에 대해 서 는 크기 조정 비 를 곱 해 야 합 니 다.
타 오 바 오 flexible.js 에 서 는 화면 크기 조정 방법 이 있 습 니 다.여기 서 직접 들 어 갑 니 다.

// util.js       
export function getDeviceRatio(){
  var isAndroid = window.navigator.appVersion.match(/android/gi);
  var isIPhone = window.navigator.appVersion.match(/iphone/gi);
  var devicePixelRatio = window.devicePixelRatio;
  var dpr;
  if (isIPhone) {
    // iOS ,  2 3  , 2    ,    1   
    if (devicePixelRatio >= 3) {        
      dpr = 3;
    } else if (devicePixelRatio >= 2){
      dpr = 2;
    } else {
      dpr = 1;
    }
  } else {
    //      ,    1    
    dpr = 1;
  }
  return dpr
}


import{ DEVICE_RATIO} from '../base/js/api.js'
/*       */
const DEVICE_RATIO=getDeviceRatio();


 /*    */
const DOWN_CONFIG={
 threshold:80*DEVICE_RATIO,
 stop:40*DEVICE_RATIO
}
/*    */
const UP_CONFIG={
 threshold:-80*DEVICE_RATIO,
}

this.scroller = new BScroll(scrollWrap,{
 click:true,
 probeType:3,
 pullDownRefresh:DOWN_CONFIG,
 pullUpLoad:UP_CONFIG
});

실례 화 된 후,다음은 상 라 와 하 라 사건 을 감청 하 는 것 이다.better Scroll 에 이벤트 가 추가 되 었 습 니 다.주로 다음 과 같 습 니 다.

/*    */
this.scroller.on('pullingDown',()=> {});

/*    */
this.scroller.on('pullingUp',()=>{});
위로 당기 거나 아래로 당기 기 이 벤트 를 실행 한 후,this.scroller.finishPullDown()또는 this.scroller.finishPullUp()을 호출 하여 better-scroll 이벤트 가 완료 되 었 음 을 알려 야 합 니 다.
대체적인 절 차 는 이렇다.

this.scroller.on('pullingDown',()=> {
  
  <!-- 1.          -->
  
  <!-- 2.      ,       -->
  
  <!-- 3.   data  , nextTick  refresh -->
});
일반적으로 작업 이 끝 난 후에 우 리 는 수 동 으로 refresh 방법 을 터치 하여 스크롤 가능 한 거 리 를 다시 계산 해 야 하기 때문에 watch 감청 데이터 의 변 화 를 쓸 수 있 습 니 다.그러면 우 리 는 데 이 터 를 바 꾸 기만 하면 됩 니 다.데 이 터 를 조작 할 때마다 refresh 방법 을 사용 하지 않 아 도 됩 니 다.

watch:{
 dataList(){
  this.$nextTick(()=>{
   this.scroller.refresh(); 
  }) 
 }
},
만약 당신 이 사용 한 버 전이 오래된 것 이 라면,on(scroll)이벤트 때 판단 하여 기능 을 실현 할 수 있 습 니 다.

this.scroller.on("scroll",(pos)=>{ 
  //           
  var height=getStyle(scroller,"height");

  //      wrap   
  var pageHeight=getStyle(scrollWrap,"height");

  //         
  var distance=80*DEVICE_RATIO;

  //  pos     

  if(pos.y>distance){ 

    //console.log("  ");
    //do something
   
  }else if(pos.y-pageHeight<-height-distance){

    //console.log("  ");
    //do something
  }

여러 번 의 트리거 를 방지 하기 위해 서 는 스위치 류 2 개 를 추가 해 야 합 니 다.

var onPullUp=true;

var onPullDown=true;
사건 이 발생 할 때마다Φ목 관 을 false 로 설정 하고 작업 이 끝 난 후에 true 로 다시 설정 합 니 다.그렇지 않 으 면 여러 번 내리 거나 위로 당기 면 여러 번 이벤트 가 발생 합 니 다.스위치 를 설정 하면 매번 하나의 사건 만 진행 되 는 것 을 보증 할 수 있다.
마지막 으로 구성 요소 로 밀봉 합 니 다.

 <template>
  <div ref="wrapper" class="list-wrapper"> 
    <div class="scroll-content">    
      <slot></slot>     
    </div>   
  </div>
</template>
페이지 마다 스크롤 해 야 할 구체 적 인 내용 이 다 르 기 때문에 하나의 슬롯 으로 나 누 어 주 었 습 니 다.
구성 요소 에 필요 한 매개 변 수 는 부모 급 으로 전 송 됩 니 다.prop 를 통 해 기본 값 을 받 고 설정 합 니 다.

 export default {
  props: {
   dataList:{
    type: Array,
    default: []
   },
   probeType: {
    type: Number,
    default: 3
   },
   click: {
    type: Boolean,
    default: true
   },  
   pullDownRefresh: {
    type: null,
    default: false
   },
   pullUpLoad: {
    type: null,
    default: false
   },  
  }

구성 요소 마 운 트 후 이벤트 가 실 행 될 때 이 벤트 를 직접 처리 하지 않 고 부모 급 에 이 벤트 를 보 냅 니 다.부모 급 은 템 플 릿 v-on 에서 이 벤트 를 받 고 후속 논 리 를 처리 합 니 다.

mounted() {
  this.scroll = new BScroll(this.$refs.wrapper, {
      probeType: this.probeType,
      click: this.click,    
      pullDownRefresh: this.pullDownRefresh,
      pullUpLoad: this.pullUpLoad,
    })

  this.scroll.on('pullingUp',()=> {
    if(this.continuePullUp){
      this.beforePullUp();
      this.$emit("onPullUp","    :    ");
    }
  });

  this.scroll.on('pullingDown',()=> {
    this.beforePullDown();
    this.$emit("onPullDown","    :      ");
  }); 
}

부모 구성 요 소 를 사용 할 때 설정 매개 변수 Props 와 하위 구성 요소 가 발사 하 는 사건 을 처리 하고 구체 적 인 내용 으로 slot 탭 을 교체 해 야 합 니 다.

  <Scroller 
    id="scroll"
    ref="scroll" 
    :dataList="filmList"
    :pullDownRefresh="DOWN_CONFIG"
    :pullUpLoad="UP_CONFIG"
    @onPullUp="pullUpHandle"
    @onPullDown="pullDownHandle"
   >

    <ul>
       <router-link class="film-list" v-for="(v,i) in filmList" :key="v.id" tag="li" :to='{path:"/film-detail/"+v.id}'>
          <div class="film-list__img">
             <img v-lazy="v.images.small" alt="" />        
          </div>
          <div class="film-list__detail">
            <p class="film-list__detail__title">{{v.title}}</p>
            <p class="film-list__detail__director">  :{{filterDirectors(v.directors)}}</p>
            <p class="film-list__detail__year">  :{{v.year}}<span>{{v.stock}}</span></p>
            <p class="film-list__detail__type">  :{{v.genres.join(" / ")}}<span></span></p>
            <p class="film-list__detail__rank">  :<span>{{v.rating.average}} </span></p>
          </div>             
        </router-link>
     </ul>     
   </Scroller>

부모 구성 요 소 는 this.$refs.xxx 를 통 해 하위 구성 요 소 를 가 져 올 수 있 습 니 다.하위 구성 요소 의 방법 을 호출 할 수 있 습 니 다.

 computed:{
    scrollElement(){
      return this.$refs.scroll
    }
  }
전체 scroller 구성 요소 의 내용 은 다음 과 같 습 니 다.

   <template>
     <div ref="wrapper" class="list-wrapper"> 
       <div class="scroll-content">    
         <slot></slot>
         <div>
           <PullingWord v-show="!inPullUp&&dataList.length>0" :loadingWord="beforePullUpWord"></PullingWord>
           <Loading v-show="inPullUp" :loadingWord='PullingUpWord'></Loading>
         </div>    
       </div> 

       <transition name="pullDown">
         <Loading class="pullDown" v-show="inPullDown" :loadingWord='PullingDownWord'></Loading>
       </transition> 
     </div>
   </template>


   <script >
    import BScroll from 'better-scroll'
    import Loading from './loading.vue'
    import PullingWord from './pulling-word'

    const PullingUpWord="       ...";
    const beforePullUpWord="      ";
    const finishPullUpWord="    ";

    const PullingDownWord="   ...";

    export default {
     props: {
      dataList:{
       type: Array,
       default: []
      },
      probeType: {
       type: Number,
       default: 3
      },
      click: {
       type: Boolean,
       default: true
      },  
      pullDownRefresh: {
       type: null,
       default: false
      },
      pullUpLoad: {
       type: null,
       default: false
      },  
     },
     data() {
       return { 
         scroll:null,
         inPullUp:false,
         inPullDown:false,
         beforePullUpWord,
         PullingUpWord,
         PullingDownWord,
         continuePullUp:true
       }
     },
      
     mounted() {
       setTimeout(()=>{
         this.initScroll();

         this.scroll.on('pullingUp',()=> {
           if(this.continuePullUp){
             this.beforePullUp();
             this.$emit("onPullUp","    :    ");
           }
         });

         this.scroll.on('pullingDown',()=> {
           this.beforePullDown();
           this.$emit("onPullDown","    :      ");
         });

       },20)
       
     },
     methods: {
       initScroll() {
         if (!this.$refs.wrapper) {
           return
         }
         this.scroll = new BScroll(this.$refs.wrapper, {
           probeType: this.probeType,
           click: this.click,    
           pullDownRefresh: this.pullDownRefresh,
           pullUpLoad: this.pullUpLoad,
         })
       },
       beforePullUp(){
         this.PullingUpWord=PullingUpWord;
         this.inPullUp=true;
       }, 
       beforePullDown(){
         this.disable();
         this.inPullDown=true;
       },
       finish(type){
         this["finish"+type]();
         this.enable();
         this["in"+type]=false; 
       },
       disable() {
         this.scroll && this.scroll.disable()
       },
       enable() {
         this.scroll && this.scroll.enable()
       },
       refresh() {
         this.scroll && this.scroll.refresh()
       }, 
       finishPullDown(){
         this.scroll&&this.scroll.finishPullDown()
       },
       finishPullUp(){
         this.scroll&&this.scroll.finishPullUp()
       },   
     },
        
     watch: {
       dataList() {        
         this.$nextTick(()=>{
           this.refresh();            
         }) 
       }
     },
     components: {
       Loading,
       PullingWord
     }
    }

   </script>

구체 적 인 내용 은 github 를 볼 수 있 고 프로젝트 주 소 는 다음 과 같다https://github.com/linrunzheng/vueApp
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기