国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Vue 實現的音樂項目 music app 知識點總結分享

meteor199 / 1466人閱讀

摘要:后兩個屬性可選。屬性定義了項目的縮小比例,默認為,即如果空間不足,該項目將縮小。屬性定義了在分配多余空間之前,項目占據的主軸空間。它的默認值為,即項目的本來大小。結合的異步組件和的代碼分割功能,輕松實現路由組件的懶加載。

項目總結

這是我第二個用 Vue 實現的項目,下面內容包括了在實現過程中所記錄的知識點以及一些小技巧

項目演示地址:https://music-vue.n-y.io
源代碼地址:https://github.com/nanyang24/...

其他

此應用的全部數據來自 QQ音樂,利用 axios 結合 node.js 代理后端請求抓取

全局通用的應用級狀態使用 vuex 集中管理

全局引入 fastclick 庫,消除 click 移動瀏覽器 300ms 延遲

頁面是響應式的,適配常見的移動端屏幕,采用 flex 布局

疑難總結 & 小技巧 關于 Vue 知識 & 使用技巧 v-html 可以轉義字符,處理特定接口很有用 watch 對象可以觀測 屬性 的變化 像這種父組件傳達子組件的參數通常都是在data()里面定義的,為什么這里要放到created()定義,兩者有什么區別呢?

因為這個變量不需要觀測它的變化,因此不用定義在 data 里,這樣也會對性能有所優化

不明白什么時候要把變量放在data()里,什么時候又不需要放 ?

需要監測這個數據變化的時候,放在 data() 里,會給數據添加 getter 和 setter

生命周期 鉤子函數

生命周期鉤子函數,比如 mounted 是先觸發子組件的 mounted,再會觸發父組件的 mounted,但是對于 created 鉤子,又會先觸發父組件,再觸發子組件。

銷毀計數器

如果組件有計數器,在組件銷毀時期要記得清理,好習慣

對于 Vue 組件,this.$refs.xxx 拿到的是 Vue 實例,所以需要再通過 $el 拿到真實的 dom 關于 JS 知識 & 技巧 setTimeout(fn, 20)

一般來說 JS 線程執行完畢后一個 Tick 的時間約17ms內 DOM 就可以渲染完畢所以課程中 setTimeout(fn, 20) 是非常穩妥的寫法

關于 webpack 知識 & 技巧 " ~ " 使 SCSS 可以使用 webpack 的相對路徑
@import "~common/scss/mixin";
@import "~common/scss/variable";
babel-runtime 會在編譯階段把 es6 語法編譯的代碼打包到業務代碼中,所以要放在dependencies里。 Fast Click 是一個簡單、易用的庫,專為消除移動端瀏覽器從物理觸摸到觸發點擊事件之間的300ms延時 為什么會存在延遲呢?

從觸摸按鈕到觸發點擊事件,移動端瀏覽器會等待接近300ms,原因是瀏覽器會等待以確定你是否執行雙擊事件

何時不需要使用

FastClick 不會伴隨監聽任何桌面瀏覽器

Android 系統中,在頭部 meta 中設置 width=device-width 的Chrome32+ 瀏覽器不存在300ms 延時,所以,也不需要

同樣的情況也適用于 Android設備(任何版本),在viewport 中設置 user-scalable=no,但這樣就禁止縮放網頁了

IE11+ 瀏覽器中,你可以使用 touch-action: manipulation; 禁止通過雙擊來放大一些元素(比如:鏈接和按鈕)。IE10可以使用 -ms-touch-action: manipulation

請求接口

jsonp:

XHR:

手寫輪播圖

利用 BScroll

BScroll 設置 loop 會自動 clone 兩個輪播插在前后位置

如果輪播循環播放,是前后各加一個輪播圖保證無縫切換,所以需要再加兩個寬度

if (this.loop) {
  width += 2 * sliderWidth
}

初始化 dots 要在 BScroll 克隆插入兩個輪播圖之前

dots active狀態 是通過判斷 currentIndex 與 index 是否相等

currentIndex 更新是通過獲取 scroll 當前 page,BScroll 提供了 api 方便調用

this.currentPageIndex = this.scroll.getCurrentPage().pageX

為了保證改變窗口大小依然正常輪播,監聽窗口 resize 事件,重新渲染輪播圖

window.addEventListener("resize", () => {
  if (!this.scroll || !this.scroll.enabled) return

  clearTimeout(this.resizeTimer)
  this.resizeTimer = setTimeout(() => {
    if (this.scroll.isInTransition) {
      this._onScrollEnd()
    } else {
      if (this.autoPlay) {
        this._play()
      }
    }
    this.refresh()
  }, 60)
})

在切換 tab 相當于 切換了 keep-alive 的組件
輪播會出問題,需要手動幫助執行,利用了 activated , deactivated 鉤子函數

activated() {
  this.scroll.enable()
  let pageIndex = this.scroll.getCurrentPage().pageX
  this.scroll.goToPage(pageIndex, 0, 0)
  this.currentPageIndex = pageIndex
  if (this.autoPlay) {
    this._play()
  }
},
deactivated() {
  this.scroll.disable()
  clearTimeout(this.timer)
}

實測,首次打開網頁并不會執行 activated,只有在之后切換 tab ,切回來才會執行

在組件銷毀之前 beforeDestroy 銷毀定時器是好習慣,keep-alive 因為是將組件緩存了,所以不會觸發

beforeDestroy() {
  this.scroll.disable()
  clearTimeout(this.timer)
}
后端接口代理

簡單設置一下 Referer, Host,讓別人直接通過瀏覽器抓到你的接口
但是這種方式防不了后端代理的方式

前端 XHR 會有跨域限制,后端發送 http 請求則沒有限制,因此可以偽造請求

axios 可以在瀏覽器端發送 XMLHttpRequest 請求,在服務器端發送 http 請求

(在項目編寫階段,可以將后端代理請求寫在 webpack 的 dev 文件的 before 函數內)

before(app) {
  app.get("/api/getDiscList", function (req, res) {
    const url = "https://c.y.qq.com/splcloud/fcgi-bin/fcg_get_diss_by_tag.fcg"
    axios.get(url, {
      headers: {
        referer: "https://c.y.qq.com/",
        host: "c.y.qq.com"
      },
      params: req.query
    }).then((response) => {
      res.json(response.data) // axios 返回的數據在 response.data,要把數據透傳到我們自定義的接口里面 res.json(response.data)
    }).catch((e) => {
      console.log(e)
    })
  });
}

定義一個路由,get 到一個 /api/getDiscList 接口,通過 axios 偽造 headers,發送給QQ音樂服務器一個 http 請求,還有 param 參數。
得到服務端正確的響應,通過 res.json(response.data) 返回到瀏覽器端

另外 因為是 http 請求數據,是ajax,所以 format 參數要將原本接口的 jsonp 改為 json

大公司怎么防止被惡意代理呢?當你的訪問量大的時候,出口ip會被查到獲取封禁,還有一種就是參數驗簽,也就是請求人家的數據必須帶一個簽名參數,然后這個簽名參數是很難拿到的這個正確的簽名,從而達到保護數據的目的

當然,獲取的數據并不能直接拿來用,需要做進一步的規格化,達到我們使用的要求,所以在這方面多帶帶封裝了一個 class 來處理這方面的數據,具體請看src/common/js/song.js

flex 布局,熱門歌單推薦

左側 icon 固定大小,flex: 0 0 60px

flex 屬性是 flex-grow , flex-shrinkflex-basis 的簡寫,默認值為 0 1 auto。后兩個屬性可選。

flex-grow 屬性定義項目的放大比例,默認為 0,即如果存在剩余空間,也不放大。

flex-shrink 屬性定義了項目的縮小比例,默認為 1,即如果空間不足,該項目將縮小。

flex-basis 屬性定義了在分配多余空間之前,項目占據的主軸空間(main size)。瀏覽器根據這個屬性,計算主軸是否有多余空間。它的默認值為auto,即項目的本來大小。

右側 text 區塊 自適應占據剩下的空間,并且內部也采用 flex,使用 flex-direction: column; justify-content: center; 來達到縱向居中排列

recommend 頁面 利用 BScroll 滾動

Scroll 初始化但卻沒有滾動,是因為初始化時機不對,必須保證數據到來,DOM 成功渲染之后 再去進行初始化
可以使用父組件 給 Scrol組件傳 :data 數據,Scroll 組件自己 watch 這個 data,有變化就立刻 refesh 滾動

新版本 BScroll 已經自己實現檢測 DOM 變化,自動刷新,大部分場景下無需傳 data 了

所以也就 無需監聽 img 的 onload 事件 然后執行 滾動刷新 了

    
  
  
修復進度條的 BUG

迷你播放器暫停狀態,進入全屏,按鈕在進度條最左邊

原因:當播放器最小化的時候,progress-bar 仍然在監聽 percent 的變化,所以在不斷計算進度條的位置,然而這個時候由于播放器隱藏,進度條的寬度 this.$refs.progressBar.clientWidth 計算為0,因此計算出來的 offset 也是不對的,導致再次最大化播放器的時候,由于播放器是暫停狀態, percent 并不會變化,也不會重新計算這個 offset ,導致 Bug。

解決方案:當播放器最大化的時候,手動去計算一次 offset,確保進度條的位置正確。

progress-bar 組件要 watch 下 fullScreen,在進入全屏的時候調用一下 移動按鈕函數

歌詞 lyric

獲取歌詞,雖然我們約定返回數據是 json,但QQ音樂 返回的是依然是 jsonp,所以我們需要做一層數據的處理

const reg = /^w+(({.+}))$/
就是將返回的jsonp格式摘取出我們需要的json字段

ret = JSON.parse(matches[1])
將正則分組(就是正則括號內的內容)捕獲的json字符串數據 轉成 json 格式

然后我們在 player 組件中監聽 currentSong 的變化,獲取 this.currentSong.getLyric()

axios.get(url, {
  headers: {
    referer: "https://c.y.qq.com/",
    host: "c.y.qq.com"
  },
  params: req.query
}).then((response) => {
  let ret = response.data
  if (typeof ret === "string") {
    const reg = /^w+(({.+}))$/
    const matches = ret.match(reg)
    if (matches) {
      ret = JSON.parse(matches[1])
    }
  }
  res.json(ret)
})

然后我們得到的返回數據的是 base64 的字符串,需要解碼,這里用到了第三方庫: js-base64
(我們這次用的是QQ音樂pc版的歌詞,需要解碼base64,而移動版的QQ音樂是不需要的)

this.lyric = Base64.decode(res.lyric)

之后利用第三方庫: js-lyric ,解析我們的歌詞,生成方便操作的對象

getLyric() {
  this.currentSong.getLyric()
    .then(lyric => {
      this.currentLyric = new Lyric(lyric)
    })
}
歌詞滾動

當前歌曲的歌詞高亮是利用 js-lyric 會派發的 handle 事件

 this.currentLyric = new Lyric(lyric, this.handleLyric)

js-lyric 會在每次改變當前歌詞時觸發這個函數,函數的參數為 當前的 lineNum 和 txt

而 使當前高亮歌詞保持最中間 是利用了 BScroll 滾動至高亮的歌詞
let middleLine = isIphoneX() ? 7 : 5  // 鑒于iphonex太長了,做個小優化
if (lineNum > middleLine) {
  let lineEl = this.$refs.lyricLine[lineNum - middleLine]
  this.$refs.lyricList.scrollToElement(lineEl, 1000)
} else {
  this.$refs.lyricList.scrollTo(0, 0, 1000)
}
cd 與 歌詞 之間滑動

通過監聽 middle 的 三個 touch 事件

offsetWidth 是為了計算歌詞列表的一個偏移量的,首先它的偏移量不能大于0,也不能小于 -window.innerWidth
left 是根據當前顯示的是 cd 還是歌詞列表初始化的位置,如果是 cd,那么 left 為 0 ,歌詞是從右往左拖的,deltaX 是小于 0 的,所以最終它的偏移量就是 0+deltaX;如果已經顯示歌詞了,那么 left 為 -window.innerWidth,歌詞是從左往右拖,deltaX 是大于 0 的,所以最終它的偏移量就是 -window.innerWidth + deltaX

middleTouchStart(e) {
  this.touch.initiated = true
  this.touch.startX = e.touches[0].pageX
  this.touch.startY = e.touches[0].pageY
},
middleTouchMove(e) {
  if (!this.touch.initiated) return
  const deltaX = e.touches[0].pageX - this.touch.startX
  const deltaY = e.touches[0].pageY - this.touch.startY
  if (Math.abs(deltaY) > Math.abs(deltaX)) {
    return
  }
  const left = this.currentShow === "cd" ? 0 : -window.innerWidth
  const offsetWidth = Math.min(0, Math.max(-window.innerWidth, left + deltaX))
  this.touch.percent = Math.abs(offsetWidth / window.innerWidth)
  console.log(this.touch.percent)
  this.$refs.lyricList.$el.style[transform] = `translate3d(${offsetWidth}px,0,0)`
  this.$refs.lyricList.$el.style[transitionDuration] = 0
  this.$refs.middleL.style.opacity = 1 - this.touch.percent
  this.$refs.middleL.style[transitionDuration] = 0
},
middleTouchEnd() {
  let offsetWidth, opacity
  // 從右向左滑 的情況
  if (this.currentShow === "cd") {
    if (this.touch.percent > 0.1) {
      offsetWidth = -window.innerWidth
      opacity = 0
      this.currentShow = "lyric"
    } else {
      offsetWidth = 0
      opacity = 1
    }
  } else {
    //  從左向右滑 的情況
    if (this.touch.percent < 0.9) {
      offsetWidth = 0
      opacity = 1
      this.currentShow = "cd"
    } else {
      offsetWidth = -window.innerWidth
      opacity = 0
    }
  }
  const durationTime = 300
  this.$refs.lyricList.$el.style[transform] = `translate3d(${offsetWidth}px,0,0)`
  this.$refs.lyricList.$el.style[transitionDuration] = `${durationTime}ms`
  this.$refs.middleL.style.opacity = opacity
  this.$refs.middleL.style[transitionDuration] = `${durationTime}ms`
}
優化

Vue 按需加載路由:

當打包構建應用時,Javascript 包會變得非常大,影響頁面加載。如果我們能把不同路由對應的組件分割成不同的代碼塊,然后當路由被訪問的時候才加載對應組件,這樣就更加高效了。

結合 Vue 的異步組件Webpack 的代碼分割功能,輕松實現路由組件的懶加載。

首先,可以將異步組件定義為返回一個 Promise 的工廠函數 (該函數返回的 Promise 應該 resolve 組件本身):

const Foo = () => Promise.resolve({ /* 組件定義對象 */ })

第二,在 Webpack 2 中,我們可以使用動態 import語法來定義代碼分塊點 (split point):

import("./Foo.vue") // 返回 Promise

在我們的項目中的 router/index.js 是這樣定義的:

// Vue 異步加載路由
// 引入5個 一級路由組件
const Recommend = () => import("components/recommend/recommend")
const Singer = () => import("components/singer/singer")
const Rank = () => import("components/rank/rank")
const Search = () => import("components/search/search")
const UserCenter = () => import("components/user-center/user-center")
// 二級路由組件
const SingerDetail = () => import("components/singer-detail/singer-detail")
const Disc = () => import("components/disc/disc")
const TopList = () => import("components/top-list/top-list")

無需改動其他的代碼

手機聯調

電腦,手機 同一WIFI下

配置 config 的 index.js 里的 host 為 "0.0.0.0",手機可以打開電腦的IP地址+端口查看

mac下 ifconfig 查看ip

移動端調試工具

移動端console:vConsole
移動端抓包工具:charles

結語

以上是在實現這個音樂 Vue 項目中遇到的難點以及一些使用技巧。在這里記錄下來方便以后自己查閱,還能夠給同樣在前端這個小領域奮斗的大家提供一小些學習資料~

我的 Github:https://github.com/nanyang24
如果對你有幫助,歡迎 star 和 互粉 ~

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107496.html

相關文章

  • 讓工作與音樂Vue)相伴

    摘要:前言最近在自學打算自己仿一個項目來實戰一下,由于本人很喜歡聽歌,所以就選擇了網易云音樂,在這與大家分享一下自己所遇到的問題,其中也有些不足之處也希望大家提一些寶貴的意見,互相學習,一起進步。 showImg(https://segmentfault.com/img/remote/1460000015805758); 前言 最近在自學vue,打算自己仿一個項目來實戰一下,由于本人很喜歡聽...

    jemygraw 評論0 收藏0
  • ?基于H5+js開發一款音樂播放器

    前言:當下音樂播放器不勝其數,為了更好的掌握一些東西,我們來自己制作一個音樂播放器。 文章目錄: 一.開發環境:二.頁面視圖:1.主文件入口(首頁):2.音樂播放界面: 三.功能實現(1)、index.html:(2)、播放音樂(music.html):(3)、樣式文件(index.css): 四.項目地址: 一.開發環境: 開發工具:HbuliderX; 框架:Vant,Mui,V...

    BearyChat 評論0 收藏0
  • vue-music(1)音樂播發器 項目開發記錄

    摘要:在中新建組件許文瑞正在吃屎。。。。在中添加如下代碼三歌手組件開發歌手首頁開發數據獲取數據獲取依舊從音樂官網獲取歌手接口創建我們和以前一樣,利用我們封裝的等發放,來請求我們的接口,返回給。 Vue-Music 跟學一個網課老師做的仿原生音樂APP跟學的筆記,記錄點滴,也希望對學習vue初學小伙伴有點幫助 showImg(https://segmentfault.com/img/remot...

    happen 評論0 收藏0
  • 給自己網站添加網易云音樂歌單吧^ ^

    摘要:每次用網易云音樂客戶端播放聽歌的時候,收藏的歌曲,在我的博客上也可以同步進行更新。 最近應該發現,我的博客https://blog.codelabo.cn左下角多了一個音樂播放器 showImg(https://segmentfault.com/img/remote/1460000016786096?w=1806&h=952); 這個是怎么實現的?一起來看看吧 APlayer 首先我們...

    RaoMeng 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<