vue2学习仿qq音乐的心路历程

随着互联网的高速发展,技术不断的更新迭代,web这一领域技术发展更是快的不行,几年前风靡全球的jQuery,现在看来也遇到了瓶颈,现在web更是讲究框架模块化开发,react/vue/angular等框架就是这web发展所需的时代产物,好了,感慨就到这里吧。。。。。。第一次发博,算是学习之路的一个记录

1.这里主要记录一下qq音乐接口变化的问题,之前qq音乐歌曲地址是不需要vkey这样的参数的,视频上讲的只能指引你,真要掌握、吃透还得靠自己去不断查找,不断发现。所以说,朋友们,发现自己不懂的问题,才是最重要的。


这里贴出视频里suggest.vue的代码

searchMore() {
        if (!this.hasMore) {
          return
        }
        this.page++
        search(this.query, this.page, this.showSinger, perpage).then((res) => {
          if (res.code === ERR_OK) {
            this.result = this.result.concat(this._genResult(res.data))
            this._checkMore(res.data)
          }
        })
      }
_genResult(data) {
        let ret = []
        if (data.zhida && data.zhida.singerid) {
          ret.push({...data.zhida, ...{type: TYPE_SINGER}})
        }
        if (data.song) {
          ret = ret.concat(this._normalizeSongs(data.song.list))
        }
        return ret
      }
_normalizeSongs(list) {
        let ret = []
        list.forEach((musicData) => {
          if (musicData.songid && musicData.albummid) {
            ret.push(createSong(musicData))
          }
        })
        return ret
      }

然后是qq音乐接口变化后(需要vkey等参数),缺什么,我们就去找什么

1.首先到api/singer.js下加一个获取vkey的方法

export function getSongVkey (songmid) { // 获取歌曲的vkey
    const url = '/getVkey'

    const data = Object.assign({}, commonParams, {
        callback: 'get002341',
        jsonpCallback: 'get002341',
        loginUin: 0,
        hostUin: 0,
        format: 'jsonp',
        platform: 'yqq',
        needNewCode: 0,
        data: `{"req":{"module":"CDN.SrfCdnDispatchServer","method":"GetCdnDispatch","param":{"guid":"5416664912","calltype":0,"userip":""}},"req_0":{"module":"vkey.GetVkeyServer","method":"CgiGetVkey","param":{"guid":"5416664912","songmid":["${songmid}"],"songtype":[0],"uin":"0","loginflag":1,"platform":"20"}},"comm":{"uin":0,"format":"json","ct":20,"cv":0}}`
    })

    return axios.get(url,{
        params:data
    }).then((res) => {
        return Promise.resolve(res.data)
    }).catch((e) => {
        console.log(e)
    })
}

2.然后到webpack.dev.conf.js中去设置代理请求数据

app.get('/getVkey', function (req, res) {//这里的路径是给前端发送请求的url
            const url = 'https://u.y.qq.com/cgi-bin/musicu.fcg'
            // axios发送get请求,可以自己配置config
            axios.get(url, {
                headers: {
                    referer: 'https://y.qq.com/',
                    host: 'u.y.qq.com'
                },
                //  params是即将与请求一起发送的url参数,无格式对象/URLSearchParams对象
                params: req.query
            }).then((response) => {
                let rest = response.data
                if(typeof rest === 'string') {
                    let reg = /^\w+\(({[^()]+})\)$/
                    let matches = rest.match(reg)
                    if(matches) {
                        rest = JSON.parse(matches[1])
                    }
                }
                res.json(rest)
            }).catch((e) => {
                console.log(e)
            })
        })

这里是我们需要的url

 以及需要的参数字段及内容

 重点是域名后面的参数,不要太刻意关注域名,这是音乐文件的真实地址

 common/js/song.js  createSong方法参数内容变化

export function createSong(musicData, filename, vkey) {
    return new Song({
        id: musicData.songid,
        mid: musicData.songmid,
        singer: filterSinger(musicData.singer),
        name: musicData.songname,
        album: musicData.albumname,
        duration: musicData.interval,
        image: `https://y.gtimg.cn/music/photo_new/T002R300x300M000${musicData.albummid}.jpg?max_age=2592000`,
        url: `http://dl.stream.qqmusic.qq.com/${filename}?guid=5416664912&vkey=${vkey}&uin=0&fromtag=66`
    })
}

2.最后是自己不断的摸索,不断的查找,然后到思否上提问,才找到解决问题的关键所在

先贴出自己suggest.vue的三个函数变化

_normalizeSongs(list, callback) {
            if(!list) {
                return
            }
            let rest = []
            let index = 1
            list.forEach((musicData) => {
                if(musicData.songid && musicData.albummid) {
                    let promise = getSongVkey(musicData.songmid) //获取歌曲filename及vkey
                    promise.then((res) => {
                        if(res.code === ERR_OK) {
                            const filename = res.req_0.data.midurlinfo[0].filename
                            const vkey = res.req_0.data.midurlinfo[0].vkey
                            const newSong = createSong(musicData, filename, vkey)
                            // console.log(newSong)
                            rest.push(newSong)  //将获取到的歌曲加入到数组中
                            if(index === list.length) {
                                callback && callback(rest)
                            }
                            index++
                        }
                    })
                }
            })
        }
_genResult(data, callback) {
            let rest = []
            if(data.zhida && data.zhida.singername) {
                rest.push({...data.zhida,...{type: TYPE_SINGER}})
            }
            if(data.song) {
                this._normalizeSongs(data.song.list, (restdata) => {
                    rest = rest.concat(restdata)
                    callback && callback(rest)
                })
            }
        }
search() {
            this.hasMore = true
            this.page = 1   //当query发生改变时,page重置为1
            this.$refs.suggest.scrollTo(0, 0)
            search(this.query, this.page, this.showSinger, Perpage).then((res) => {
                if(res.code === ERR_OK) {
                    this._genResult(res.data, (rest) => {
                        // console.log(rest)
                        this.result = rest
                    })
                    this._checkMore(res.data)
                }
            })
        }

其中searchMore方法也有小小变化

searchMore() {
            if(!this.hasMore) {
                return
            }
            this.page++
            search(this.query, this.page, this.showSinger, Perpage).then((res) => {
                if(res.code === ERR_OK) {
                    this._genResult(res.data, (rest) => {
                        this.result = this.result.concat(rest) //把新搜索到的数据拼接到之前搜索到的数据中
                    })
                    this._checkMore(res.data)
                }
            })
        }

!!!重点来了,要考的

对比之后会发现,视频里的_normalizeSongs方法和_genResult方法会有一个return的值,我的问题就在这里,因为qq音乐接口参数变化后,需要用到getSongVkey这个方法,这个方法返回的是promise对象,然而我要在循环里执行这个异步方法,没办法在循环外return想要的结果,最后在思否上提问,得到道友的解惑,通过callback这个参数得到我想要的return,在promise.then()中call&&callback(rest),自己想要的结果就会被这个rest收留,然后在其他函数里进行下一步操作,总结说来视频里的某个函数return的结果也是被另外的函数当做参数来进行下一步操作,方法不同,思路不同,得到的结果却是相同的,关键是怎么去看待问题,才能采取相应的方法去应对;思否提问地址https://segmentfault.com/q/1010000016912296,感兴趣的可以去看看,漫漫学习路,记一笔。。。

 
 
 

猜你喜欢

转载自blog.csdn.net/tmiaot/article/details/83819822