使用Vue2+webpack+Es6快速開發一個移動端項目,封裝屬於本身的jsonpAPI和手勢響應式組件

test.gif

導語

最近看到很多使用vue製做的音樂播放器,挺好玩的,原本工做中也常常使用Vue,一塊兒交流學習,好的話點個star哦

本項目特色以下 :css

1. 原生js封裝本身的跨域請求函數,支持promise調用,支持錯誤處理
2. 製做一些複用性強的vue組件,如輪播圖組件,支持手勢滑動,無限循環,圖片按需加載
3. 清晰明瞭的項目目錄

項目倉庫地址

項目演示地址

從項目中提取的banner組件地址


1、規劃目錄

一個易於維護和迭代的項目,應該是具備可靠的項目目錄的,這裏,在vue-cli生成的目錄中,加入了services、directives、utils、store等目錄,並在webpack中修改相應的導入地址:vue

Paste_Image.png

1.  services 用於全局管理接口和http請求
    2.  directives 用於添加全局指令
    3.  utils 用於放置通用js函數
    4.  store 用於管理vuex數據等

目錄


2、製做公共css,

主要採用scss+em單位+currentColor繼承父級顏色+before&after僞類製做

本項目製做的公共css有:

1. 播放器要用到的圖標
    2. 用於vue transition標籤切換時使用的css3動畫
    3. css reset
    4. 項目主題顏色,目前只能在項目初始化以前設置主題顏色,用於管理,全部組件主題顏色都來源於此

自定義公共圖標


3、全局API

分紅兩個部分:webpack

1.  jsonp分裝,負責http請求
2.  收集url地址,並放在API類上,並循環將url用bind函數導入到jsonp封裝函數中,其餘請求一樣可用

jsonp封裝

api公共類,seturl函數用於參數傳入接口地址時,用call函數直接調用services服務


4、核心組件

包括 :css3

1. banner組件
2. 播放器

1.banner組件

該組件只對傳入的數據進行處理,並相應轉化,保證了組件的通用性

Paste_Image.png

核心的函數主要是對***無限循環的處理、觸摸屏滑動,圖片按需加載***處理:

banner插件效果示意

computed : {
        sliderImg : function(){
            const [...saveImg] = this.bannerlist,    //拷貝圖片列表數據,在展現區域的圖片實際上首尾拷貝了同樣的圖片,即尾端拷貝第一張,首端拷貝最後一張
                  [imgfirst, ...other] = this.bannerlist;
            saveImg.unshift(other[other.length-1])      
            saveImg.push(imgfirst)
            return saveImg
        },
    },
    mounted () {
        if (this.bannerlist && this.bannerlist.length) {
            this.interTimer = setInterval(()=>{
                this.sliderStart()
            },3000)
        }
    },
    methods : {
        linkURl (item) {
            window.open(item[this.linkurl])
        },
        getURl (item,index) {  //用於減小一次性請求,只加載當前的圖片,加載以後添加標識
            if (!item) {
                return reloadImg
            }
            if (item.hasload) {
                return item[this.picurl]
            }
            if (this.nowSlider == index-1) {
                item.hasload = true
                return item[this.picurl]
            }
            return reloadImg
        },
        stopSlider (e) {
            e.preventDefault()
            e.stopPropagation()
            if (e.target != e.currentTarget) {  //事件委託節省下事件綁定,排除當前綁定的dom
                clearInterval(this.interTimer)
                delete this.sliderActive['transition'] //關閉css3過渡效果
                this.startTouch = e.targetTouches[0].screenX
            }
        },
        moveSlider (e) {
            e.preventDefault()
            e.stopPropagation()
            if (this.nowSlider === -1||this.nowSlider === this.bannerlist.length) {  //首端與尾端未鏈接好禁止滑動
                return;
            }
            if (e.target != e.currentTarget) {
                this.moveTouch = e.targetTouches[0].screenX
                let slideDir = this.moveTouch - this.startTouch,
                    targetWidth = parseInt(window.getComputedStyle(e.target).width),
                    tranDir;
                if (slideDir < -50 || slideDir > 50) {  //加了50容錯值,能預防觸摸時圖片忽然閃動
                    if (slideDir < 0) {  //再從新補回差值
                        slideDir -= 50
                    } else {
                        slideDir += 50
                    }
                    tranDir = -targetWidth * (this.nowSlider+1) + slideDir//觸摸時圖片隨手指移動,距離須減去當前圖片寬度乘以當前滾動索引
                    this.sliderActive.transform = `translate3d(${tranDir}px,0,0)`
                }
            }
        },
        continSilder (e) { //結束觸摸
            e.preventDefault()
            e.stopPropagation()
            if (e.target != e.currentTarget && this.moveTouch) {
                const slideDir = this.moveTouch - this.startTouch
                if (slideDir < 0) {
                    this.nowSlider ++
                } else if (slideDir > 0) {
                    this.nowSlider -- 
                }
                this.nowSlider --
                this.sliderStart() //當即設置位置
                this.moveTouch = 0  //清空手勢位置
                this.startTouch = 0
                this.interTimer = setInterval(()=>{
                    this.sliderStart()
                },3000)
            }
        },
        sliderStart () {
           this.nowSlider ++ 
           this.nowSlider %= this.sliderImg.length
           if (this.nowSlider === this.bannerlist.length) {  //向右滑動到最大值時,將位置初始化並清0 nowSlider
               setTimeout(() => { //設置一個定時器,用於異步處理,一個進行尾端拷貝的圖片的正常滑動,這個處理在差很少到達時重置,形成無限循環的錯覺
                    this.sliderActive = {
                        transform: `translate3d(-100vw,0,0)`
                    }
                    this.nowSlider = 0
               }, 500)         
            }
            if (this.nowSlider === -1) {  //向右滑動到最小值時,將位置置爲最大值
               setTimeout(() => {
                    this.nowSlider = this.bannerlist.length-1
                    this.sliderActive = {
                        transform: `translate3d(${-100*(this.nowSlider+1)}vw,0,0)`
                    }
               }, 500)       
            }
            this.sliderActive = Object.assign({},{
                transition:'transform 0.5s',
                transform: `translate3d(${-100*(this.nowSlider+1)}vw,0,0)`
            })
        } 
    }

2.播放器功能

播放器的全部功能主要依賴vuex(store.js)的控制,因爲音樂是在整個app內都播放的,故audio標籤放在了App.vue中:

store.js:
播放數據控制git

APP.vue:github

computed : {
    audioSrc : function () {  //對當前播放的音頻切換,放在頂層
      const song = this.$store.state.nowsong;
      let audioTimer;
      if (!song) {
        this.$store.state.playing = false
        clearInterval(audioTimer)
        return null
      }
      this.$store.state.playing = true
      audioTimer = setInterval(()=>{  //每秒獲取進度
        let audio = document.getElementById('m-audio');
        if (audio) {
           this.$store.state.audioProgss = audio.currentTime/audio.duration*100+'%'
        }  else {
           clearInterval(audioTimer)
        }
      },1000)
      return `${API.url.getsong}${song.songid}.m4a?fromtag=46` //播放一首歌曲
    },
    playing : function () {
       return this.$store.state.playing
    },
  },
  directives : {
    play : {  //控制是否播放
      update : function(el,binding) {
        if (binding.value) {
          el.play()
        } else {
          el.pause()
        }
      }
    }
  },

總體項目核心功能介紹到此.有好的建議儘管提哦

相關文章
相關標籤/搜索