vue 移动端音乐(3) amp;amp;gt;热门歌单推荐部分(webpack-dev-conf.js做后端接口代理+scroll插件)
1. 首先,获取歌单推荐部分的数据,与获取推荐数据不同,热门歌单数据的接口有host和referer的显示,我们的api请求被拒绝(500错误),必须要修改header,但是前端不能直接修改request header,我们采取后端接口代理的方法去解决。使用express,不是直接请求服务器的url,而是请求我们自己的server端,让local server再去请求QQ服务端
使用express启动代理服务器,原理:在getDiscList中不是直接请求url,而是请求express服务器端地址,再让我们的地址去请求服务端,使用nodejs请求服务器端,用到一个axios库,在浏览器端发送的是xmlhttprequest请求,在nodejs中发送的是http请求
我们使用axios请求服务器,在webpack-dev-conf.js中做如下配置
const express = require('express')
const axios = require('axios')
const app = express()
var apiRoutes = express.Router()
app.use('/api', apiRoutes)
在devServer{}中添加
before(app) {app.get('/api/getDiscList', (req, res) => {var 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 // 通过req从浏览器端发过来的一堆参数(platform,sin,ein等)透传给qq的服务端}).then((response)=>{ // qq服务端的响应数据,再通过res将响应数据输出到浏览器端res.json(response.data)}).catch((error)=>{console.log(error)})})}
之后,回到recommend.js中获取数据,请求的是本地express服务器的api数据(ajax请求),(本地express的数据是上边通过axios获得的)不是Jsonp数据了,返回的是axios的数据
import axios from 'axios'
export function getDiscList() {const url = '/api/getDiscList'const data = Object.assign({}, commonParams, {platform: 'yqq',hostUin: 0,sin: 0,ein: 29,sortId: 5,needNewCode: 0,categoryId: 10000000,rnd: Math.random(),format: 'json' // 将format从jsonp修改为json})return axios.get(url, {params: data}).then((res) => {return Promise.resolve(res.data)})
}
2 将获取到的数据添加到DOM中,ul-li 并编写样式
import {getRecommend, getDiscList} from 'api/recommend'
import {ERR_OK} from 'api/config'
先定义歌单的原始数据,并将其绑定到data中
data() {return {recommends: [],discList: []}},
created() {// setTimeout(() => {// this._getRecommend() // }, 2000);this._getRecommend() // 模拟loading效果// setTimeout(() => {// this._getDiscList()// }, 1000);this._getDiscList()},methods: {_getRecommend() {getRecommend().then((res) => { // res对应的就是json对象if (res.code === ERR_OK) {// console.log(res.data.slider)this.recommends = res.data.slider // 根据fcp数据的格式返回的}})},_getDiscList() {getDiscList().then((res) => {if (res.code === ERR_OK) {// console.log(res.data.list)this.discList = res.data.list}})}
填充DOM
<div class="recommend-list"><h1 class="list-title">热门歌单推荐</h1><ul><li v-for="item in discList" :key="item.id" class="item"><div class="icon"><img width="60" height="60" v-lazy="item.imgurl"></div><div class="text"><h2 class="name" v-html="item.creator.name"></h2><p class="desc" v-html="item.dissname"></p></div></li></ul></div>
3. 榜单优化:局部滚动,但是顶部不滚动,因为考虑到BScroll的复用性很大,我们将其抽象成一个组件,暂时初始化这些,如果有需要会在添加,在base下添加sroll组件
<template><div ref="wrapper"><slot></slot></div>
</template><script type="text/ecmascript-6">import BScroll from 'better-scroll'export default {props: {probeType: { // 监听滚动组价的种类type: Number,default: 1},click: { // 需不需要手动派发点击事件type: Boolean,default: true},data: {type: Array, // refresh 数据default: null},listenScroll: { // 要不要监听滚动事件type: Boolean,default: false}},mounted() { // 确保DOM被渲染setTimeout(() => {this._initScroll()}, 20)},methods: {_initScroll() {if (!this.$refs.wrapper) { // wrapper没有值的时候,直接returnreturn}this.scroll = new BScroll(this.$refs.wrapper, {probeType: this.probeType,click: this.click})// 如果要监听滚动事件,在初始化列BScroll之后要派发一个监听事件if (this.listenScroll) {// BScroll 中的this是默认指向scroll的,所以要在me中保留vue实例的thislet me = this// 监听scroll,拿到pos后,派发一个函数将pos传出去this.scroll.on('scroll', (pos) => {me.$emit('scroll', pos)}) }},enable() { // 代理方法,将scroll原生的方法都添加到我们生成的this.scroll实例上this.scroll && this.scroll.enable()},disable() {this.scroll && this.scroll.disable()},refresh() {this.scroll && this.scroll.refresh()},scrollTo() {this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments) // applay引用到上下文中},scrollToElement() {this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)}},// 要随时watch data变化时进行刷新watch: {data() {setTimeout(() => {this.refresh()}, 20)}}}
</script><style scoped lang="stylus" rel="stylesheet/stylus"></style>
4. 回到recommend.vue组件,注册并引入组件,在DOM中,我们为其添加一个内层元素div,一般在外层元素(<div class="recommend-content">)上引用ref,然后在内外层组件之间添加scroll组件,不要忘记将data传到组件中,这样data值发生变化的时候就会自动刷新了
<div class="recommend"><scroll ref="scroll" class="recommend-content" :data="discList"><div><div v-if="recommends.length" class="silder-wrapper"><slider><div v-for="item in recommends" :key="item.id"><a :href="item.linkUrl"><img :src="item.picUrl" class="needsclick" @load="loadImage"></a></div></slider></div><div class="recommend-list"><h1 class="list-title">热门歌单推荐</h1><ul><li v-for="item in discList" :key="item.id" class="item"><div class="icon"><img width="60" height="60" v-lazy="item.imgurl"></div><div class="text"><h2 class="name" v-html="item.creator.name"></h2><p class="desc" v-html="item.dissname"></p></div></li></ul></div></div><div class="loading-container" v-show="!discList.length"><loading></loading></div></scroll></div>
但是此时页面并没有滚动,mounted去初始化内容的时候页面还没有渲染,DOM被撑开时候要重新计算BScroll并refresh,才可以将BScroll正确的滚动,所以将data传入,watch观测到数据的变化,去refresh BScroll
recommend.vue中
<scroll ref="scroll" class="recommend-content" :data="discList">
在scroll.vue中,观测到data变化就去刷新bscroll
// 要随时watch data的变化watch: {data() {setTimeout(() => {this.refresh()}, 20)}}
5.recommend获取的过程是一个异步过程,图片的加载也是一个异步的过程,无法正确的获取到高度
slider(轮播图)的高度不知何时会被撑开,是没有考虑到的,所以对img进行监听,若是加载到图片,就调用scroll.vue的refresh()方法刷新,重新计算高度,这样即使slider晚两分钟加载,也不会造成BScroll的出错,因为图片加载到之后就会重新计算属性
<img :src="item.picUrl" class="needsclick" @load="loadImage">
loadImage() {if (!this.checkloaded) { // 一旦有一张图片撑开了高度,slider的高度就会被撑开this.$refs.scroll.refresh() // 调用scroll的refresh方法this.checkloaded = true // 确保逻辑只执行一次,因为只要有一张图片加载完成就会撑开高度}}
6. 为节省资源,才用图片懒加载,使用VueLazyload插件,npm安装之后,在main.js中注册,提供一张默认的图片
import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload, {loading: require('common/image/default.png')
})
在recommend.vue中,将:src="imgUrl" 换成 v-lazy ="imgUrl"
<img width="60" height="60" v-lazy="item.imgurl">
在轮播图的图片显示部分添加needsclick,使图片可以被点击
<img :src="item.picUrl" class="needsclick" @load="loadImage">
7. 开发loading组件
<template><div class="loading"><img width="24" height="24" src="./loading.gif"><p class="desc">{{title}}</p></div>
</template>
<script type="text/ecmascript-6">export default {props: {title: {type: String,default: '正在载入...'}}}
</script>
<style scoped lang="stylus" rel="stylesheet/stylus">@import "~common/stylus/variable".loadingwidth: 100%text-align: center.descline-height: 20pxfont-size: $font-size-smallcolor: $color-text-l
</style>
在recommend.vue中引用loading.vue,歌单没有数据时会出现loading
<div class="loading-container" v-show="!discList.length"><loading></loading></div>
.loading-containerposition: absolutewidth: 100%top: 50%transform: translateY(-50%)
vue 移动端音乐(3) amp;amp;gt;热门歌单推荐部分(webpack-dev-conf.js做后端接口代理+scroll插件)相关推荐
- Vue运行报错webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
vue 项目 npm run dev 运行时报错: npm ERR! xxx@1.0.0 dev: `webpack-dev-server --inline --progress --config b ...
- vue:hadoop@1.0.0 dev: `webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
运行vue项目是报错: hadoop@1.0.0 dev: `webpack-dev-server --inline --progress --config build/webpack.dev.con ...
- vue项目运行不成功--@1.0.0 dev: **`webpack-dev-server --inline --progress --config build/webpack.dev.conf.js
项目场景: vue 新项目运行–安装依赖包–运行项目 问题描述: 安装依赖包不成功-运行不起来 //mobileap----mobileap是项目名称,package.josn里name(文件夹名称) ...
- Vue实现仿音乐播放器8-实现热门榜单效果
效果 实现 热门榜单和今日推荐实现公用组件 1.今日推荐组件Today_Recommend.vue <h2>{{title}}</h2>写成动态标题 2.接受参数url等 pr ...
- vue - webpack.dev.conf.js
描述:开发时的配置.(配置开发时的一些操作) 例如这里,是否自动打开浏览器(默认true) 1 'use strict' 2 3 // build/util.js 4 const utils = re ...
- Vue进阶(五十三):vue-cli 脚手架 webpack.prod.conf.js 配置文件详解
文章目录 一.前言 二.optimize-css-assets-webpack-plugin 插件 三.拓展阅读 一.前言 webpack.prod.conf.js 配置文件是webpack生产环境核 ...
- vue移动端音乐---使用QQ音乐数据
项目预览视频:https://www.bilibili.com/video/av76348323 项目github地址:https://github.com/8127yyq/vue-musicPlay ...
- 虾米音乐关停,QQ音乐、网易云上线虾米歌单迁移功能
宋九九消息,阿里旗下平台虾米音乐发布公告称将关停虾米音乐,这个陪伴了我们12年的音乐平台就要走了,最后请在关停之前做好数据备份或导出.编辑宋九九 虾米音乐公告称: 将于2021年1月5日10点之前停止 ...
- 你们要的歌单:网易云音乐收藏量前100的歌单
网易云音乐收藏量前100的歌单,这下不怕不够循环了, 纯音乐居多,国外音乐也多,特别小众的音乐还得靠自己发现. 温暖的假日下午,你手握咖啡看着书,听着轻音乐,多么惬意. 按照收藏量降序排序 90334 ...
最新文章
- iphone objective-c内存管理
- c++ 输出二进制_Python之输入输出(input_output)
- 技术分享 |《原神》部分渲染效果分析
- 七、功能性组件与事件逻辑(IVX 快速开发教程)
- 欧盟抢先发布人工智能道德准则:AI要以人为本,负责任且无偏见
- 仿path首页滑动效果
- 调用cryptography密码学API接口计算SHA256/SHA1哈希摘要
- Protobuf C++类中成员函数GetCachedSize()与ByteSize()的区别
- 微信打飞机java 源代码_微信打飞机
- 2019每特教育蚂蚁课堂-Java互联网微服务架构面试宝典v1
- 如何使用Python查找文本文件的Zipf分布
- 绘制计算机网络拓扑图,绘制网络拓扑图1.ppt
- java idea 免费_Java程序员看过来,IDEA 2020免费版本来了
- emd经验模态分解 matlab,经验模态分解(EMD)在地球物理资料中的应用(附MATLAB程序)...
- 深圳平安银行软件测试面试,中国平安银行面试笔试题目 软件测试方向
- 1987年,国际C语言混乱代码大赛
- 【树莓派基础小实验笔记】1. 点亮LED二极管
- 4g网络什么时候淘汰_5G时代来临后,4G真的会被淘汰吗,简单说一下
- java时钟代码_一个经典的JAVA APPLET时钟程序(一)
- 外行对程序员误会有多深!扎心了!