vue music-抓取歌单列表数据(渲染轮播图)
下载安装新依赖

先添加,在npm install
main.js
import 'babel-polyfill'
import Vue from 'vue'
import App from './App'
import router from './router'
import fastclick from 'fastclick' import 'common/stylus/index.styl' Vue.config.productionTip = false // 取消点击300毫秒的延迟
fastclick.attach(document.body) /* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
头部栏引用header组件
1:
<template>
<div class="m-header">
<div class="icon"></div>
<h1 class="text">Chicken Music</h1>
<router-link tag="div" class="mine" to="/user">
<i class="icon-mine"></i>
</router-link>
</div>
</template> <script type="text/ecmascript-6">
export default {}
</script> <style scoped lang="stylus" rel="stylesheet/stylus">
@import "~common/stylus/variable"
@import "~common/stylus/mixin" .m-header
position: relative
height: 44px
text-align: center
color: $color-theme
font-size:
.icon
display: inline-block
vertical-align: top
margin-top: 6px
width: 30px
height: 32px
margin-right: 9px
bg-image('logo')
background-size: 30px 32px
.text
display: inline-block
vertical-align: top
line-height: 44px
font-size: $font-size-large
.mine
position: absolute
top:
right:
.icon-mine
display: block
padding: 12px
font-size: 20px
color: $color-theme
</style>
m-header。vue
2:在app.vue
<template>
<div id="app">
:显式
<m-header></m-header>
</div>
</template> <script>
:导入
import MHeader from './components/m-header/m-header'
export default {
components:{
:注册
MHeader
}
}
</script> <style scoped lang="stylus" rel="stylesheet/stylus"> </style>
二:导入歌手页面,搜索页面,排行榜,推荐页面
1:先在index.js入口注册这4个组件
import Reacommed from 'components/reacommed/reacommed'
import Search from 'components/search/search'
import Singer from 'components/singer/singer'
import Rank from 'components/rank/rank'
2:配置url
export default new Router({
routes: [
{
path: '/reacommed',
component:Reacommed
},
{
path:'/singer',
component:Singer
},
{
path:'/rank',
component:Rank
},
{
path:'/search',
component:Search
}
]
})
import Vue from 'vue'
import Router from 'vue-router'
import Reacommed from 'components/reacommed/reacommed'
import Search from 'components/search/search'
import Singer from 'components/singer/singer'
import Rank from 'components/rank/rank' Vue.use(Router) export default new Router({
routes: [
{
path: '/reacommed',
component:Reacommed
},
{
path:'/singer',
component:Singer
},
{
path:'/rank',
component:Rank
},
{
path:'/search',
component:Search
}
]
})
index。js
3:如何引入router实例
import 'babel-polyfill'
import Vue from 'vue'
import App from './App'
// 1这里的router是index。js的实例
import router from './router'
import fastclick from 'fastclick' import 'common/stylus/index.styl' Vue.config.productionTip = false // 取消点击300毫秒的延迟
fastclick.attach(document.body) /* eslint-disable no-new */
new Vue({
el: '#app',
//
router,
components: { App },
template: '<App/>'
})
main.js
注册url
import Vue from 'vue'
import Router from 'vue-router'
import Recommend from 'components/recommend/recommend'
import Search from 'components/search/search'
import Singer from 'components/singer/singer'
import Rank from 'components/rank/rank' Vue.use(Router) export default new Router({
routes: [
{
path: '/recommend',
component:Recommend
},
{
path:'/singer',
component:Singer
},
{
path:'/rank',
component:Rank
},
{
path:'/search',
component:Search
}
]
})
index.js
4:显示在App.vue页面
知识点:
router-linnk
a:里面有一个tag属性,控制其显示的为什么标签
如:tag=“a”,即显示为a标签
b:router-link-active
当前某个router-link被激活的时候,会添加样式
5:将导航条添加进去
a:先在app.vue导入进去tab组件
b:注册
c:渲染
<template>
<div id="app">
<m-header></m-header>
<tab></tab>
<router-view></router-view>
</div>
</template> <script>
import MHeader from './components/m-header/m-header'
import Tab from './components/tab/tab'
export default {
components:{
MHeader,
Tab
}
}
</script> <style scoped lang="stylus" rel="stylesheet/stylus"> </style>
app.vue
url重定向
redirect
三:在app.vue导入组件
import MHeader from './components/m-header/m-header'
import Tab from './components/tab/tab'
首字母要大写,因为其本质上是class,class书写规范为首字母大写
jsonp
jsonp(url, opts, fn)
url (String) url to fetch
opts (Object), optional
param : 指定回调函数名
timeout : 超时时间,默认一分钟
prefix : __jp 默认添加前缀
name
fn callback (回调函数)
四:抓取qq音乐的数据
XHR:ajax请求
1:可以自己手写
2:引用插件
下载安装jsonp
npm install jsonp
.jsonp是什么?jsonp是目前可以跨域的(基本上标签带有src属性的都是可以不受任何访问限制),且要动态生成script标签在ajax无法跨域的情况下可以使用jsonp进行请求但它跟ajax是不一样的..jsonp利用url链接进行请求发送和调用回调函数(callblack)使用数据。
1:封装一个jsonp方法
用于拼接url
import originJsonp from 'jsonp' // 引用 export default function jsonp(url, data, option) {
// 将url和data对象进行拼接成url拼接
url += (url.indexOf('?') < ? '?' : '&') + param(data)
// param 是一个拼接函数将data专门转化成url形式
return new Promise((resolve, reject) => {
originJsonp(url, option, (err, data) => {
if (!err) {
resolve(data)
} else {
reject(err)
}
})
})
} export function param(data) {
let url = ''
for (var k in data) {
let value = data[k] !== undefined ? data[k] : ''
url += '&' + k + '=' + encodeURIComponent(value)
}
return url ? url.substring() : ''
}
Promise对象有2个参数(resolve,reject)
resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从 pending 变为 resolved),
在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从 pending 变为 rejected),
在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
promise()充当异步操作和回调函数的中介,起到代理的作用
param()data数据对象转化成url格式
function param(data){
let url = '';
//遍历拼接对象
for(var k in data){
//以&a=123=yu=789 这样形式拼接
let value = data[k] !== undefined ?data[k] : '';
url += `&${k}=${encodeURIComponent(value)}`; //es6语法
}
return url ? url.substring():'';
}
在创建的config.js下写入jsonp请求通用公共参数
xport const commonParams = {
g_tk: ,
inCharset: 'utf-8',
outCharset: 'utf-8',
notice: ,
format: 'jsonp',
}
// 设置常量 param
export const options = {
param: 'jsonpCallback'
}
// 设置常量 错误信息 0 是 ok
export const ERR_OK =
recommend.js文件下写入抓取QQ音乐轮播图需要发送数据
import jsonp from '../common/js/jsonp' //引入自定义封装的jsonp函数
import { commonParams, options } from './config'
export function getRecommend() {
//轮播图请求地址
const url = 'https://c.y.qq.com/musichall/fcgi-bin/fcg_yqqhomepagerecommend.fcg';
利用es6对象方法进行浅拷贝将数组对象合并到第一个{}对象中
const data = Object.assign({}, commonParams, {
platform: 'h5',
uin: ,
needNewCode:
})
//调用jsonp方法 进行url拼接
return jsonp(url, data, options)
}
.组件页面得到数据
将其js文件引入组件中
import {getRecommend} from 'api/recommend';
import {ERR_OK} from 'api/config'g'
获取数据
_getRecommend(){
//因为return new Promise中有.then表示如果异步成功完成就执行
getRecommend().then(res=>{
if(res.code === ERR_OK){
console.log(res.data.slider)
this.recommend = res.data.slider;
//放入组件data中接着传入到轮播组件中使用v-for渲染
}
})
}
编写拼接url的方法(getRecommend)
MusicJsonCallback30832226944503405({"code":,
"subcode":,"msg":"",
"data":{"total":,"items":[{"from":,"status":,"msg_num":},
{"from":,"status":,"msg_num":},{"from":,"status":,"msg_num":},
{"from":,"status":,"msg_num":}]}})
从recommend调用getRecommend方法
推荐页面
recommend。vue
_getRecommend() {
getRecommend().then((res) => {
if(res.code === ERR_OK){
// 轮播图数据
this.recommends = res.data.slider
}
})
},
手写轮播图组件 base/slider
better-scroll文档**
slider.vue
<!-- 轮播图 -->
<template>
// slider为最外容器
<div class="slider" ref="slider">
// sliderGroup为内层容器
<div class="slider-group" ref="sliderGroup">
<slot> </slot>
</div>
</div>
</template> <script>
// 轮播图组件
import BScroll from 'better-scroll'
import {addClass} from 'common/js/dom' export default{
data(){
return {
dots:[]
}
},
props:{
loop:{
// 循环轮播
type:Boolean,
default: true
},
autoPlay:{
// 自动轮播
type:Boolean,
default: true
},
interval:{
// 时间间隔
type:Number,
default:
}
},
mounted(){
setTimeout(() =>{
this._setSliderWidth()
this._initSlider()
this._initDots()
},)
},
methods:{
_setSliderWidth(){
this.children = this.$refs.sliderGroup.children let width =
let sliderWidth = this.$refs.slider.clientWidth
for (let i = ; i < this.children.length;i++){
let child = this.children[i]
addClass(child,'slider-item') child.style.width = sliderWidth + 'px'
width += sliderWidth
}
if(this.loop){
width += * sliderWidth
}
this.$refs.sliderGroup.style.width = width + 'px'
},
_initDots() {
this.dots = new Array(this.children.length-)
},
_initSlider(){
this.slider = new BScroll(this.$refs.slider,{
scrollX:true,
scrollY:false,
momentum:false,
snap:true,
snapLoop:this.loop,
snapThreshold:0.3,
snapSpeed:,
click:true
} )
}
}
}
</script> <style scoped lang="stylus" rel="stylesheet/stylus">
@import "~common/stylus/variable" .slider
min-height: 1px
.slider-group
position: relative
overflow: hidden
white-space: nowrap
.slider-item
float: left
box-sizing: border-box
overflow: hidden
text-align: center
a
display: block
width: %
overflow: hidden
text-decoration: none
img
display: block
width: %
.dots
position: absolute
right:
left:
bottom: 12px
text-align: center
font-size:
.dot
display: inline-block
margin: 4px
width: 8px
height: 8px
border-radius: %
background: $color-text-l
&.active
width: 20px
border-radius: 5px
background: $color-text-ll
</style>
slider。vue
<div class="slider" ref="slider">---> 最外层容器
<div class="slider-group" ref="sliderGroup">---> 内层容器 sliderGroup轮播图,只能设置宽度,高度固定
:获取整个列表有多少个元素
this.children = this.$refs.sliderGroup.children :父元素的宽度,图片撑开的宽度
let sliderWidth = this.$refs.slider.clientWidth
给轮播图图片添加样式
(手动写的class,耦合性太强)
a、dom。js--->只对dom元素进行操作的方法(通用)
b、再导入dom。js
// 对dom元素操作的组件
import {addClass} from 'common/js/dom'
c、将slider-item样式添加进去
addClass(child,'slider-item') 计算部分
// 子容器的宽度 要等于父容器的宽度 需要添加单位'px'
child.style.width = sliderWidth + 'px'
// 总宽度需要+父容器的宽度
width += sliderWidth loop:{
// 循环轮播
type:Boolean,
default: true
}, // 保证其能进行循环切换,需克隆2个sliderWidth-->即宽度需要加2倍sliderWidth
if(this.loop && !isResize){
width += 2 * sliderWidth
} 最后设置宽度
this.$refs.sliderGroup.style.width = width + 'px'
问题:当后面方法需要获取数据时,而获取数据的方法还未执行完毕
在recommend。vue进行判断数据长度
<div v-if='recommends.length' class="slider-wrapper">
<slider>
<div v-for="item in recommends">
<a :href="item.linkUrl">
<img :src="item.picUrl">
</a>
</div>
</slider>
</div>
recommend.vue推荐页面
<!-- 推荐页面 -->
<template>
<div class="recommend">
<div class="recommend-content">
<!-- 轮播图 -->
<div v-if='recommends.length' class="slider-wrapper">
<slider>
<div v-for="item in recommends">
<a :href="item.linkUrl">
<img :src="item.picUrl">
</a>
</div>
</slider>
</div>
<div class="recommend-list">
<h1 class="list-title">热门歌单推荐</h1>
</div>
<ul> </ul>
</div>
</div>
</template> <script>
// 导入轮播图组件
import Slider from 'base/slider/slider'
// 导入获取轮播数据的方法
import {getRecommend} from 'api/recommend'
// 语义化下面的err_ok
import {ERR_OK} from 'api/config'
// 获取数据created
export default {
data() {
// 定义轮播图数据
return{
recommends:[]
}
},
// 钩子函数
created() {
this._getRecommend()
},
methods: {
_getRecommend() {
getRecommend().then((res) => {
if(res.code === ERR_OK){
// 轮播图数据
this.recommends = res.data.slider
}
})
}
},
components:{
Slider,
}
} </script> <style scoped lang="stylus" rel="stylesheet/stylus">
@import "~common/stylus/variable" .recommend
position: fixed
width: %
top: 88px
bottom:
.recommend-content
height: %
overflow: hidden
.slider-wrapper
position: relative
width: %
overflow: hidden
.recommend-list
.list-title
height: 65px
line-height: 65px
text-align: center
font-size: $font-size-medium
color: $color-theme
.item
display: flex
box-sizing: border-box
align-items: center
padding: 20px 20px 20px
.icon
flex: 60px
width: 60px
padding-right: 20px
.text
display: flex
flex-direction: column
justify-content: center
flex:
line-height: 20px
overflow: hidden
font-size: $font-size-medium
.name
margin-bottom: 10px
color: $color-text
.desc
color: $color-text-d
.loading-container
position: absolute
width: %
top: %
transform: translateY(-%)
</style>
推荐页面
轮播图下的圆圈
<!-- 轮播图 -->
<template>
<div class="slider" ref="slider">
<div class="slider-group" ref="sliderGroup">
<slot> </slot>
</div>
<!-- 圆圈 -->
<div class="dots">
<span class="dot" v-for = 'item in dots'></span>
</div>
</div>
</template> <script>
// 轮播图组件
import BScroll from 'better-scroll'
import {addClass} from 'common/js/dom' export default{
data(){
return {
dots:[]
}
},
props:{
loop:{
// 循环轮播
type:Boolean,
default: true
},
autoPlay:{
// 自动轮播
type:Boolean,
default: true
},
interval:{
// 时间间隔
type:Number,
default:
}
},
mounted(){
setTimeout(() =>{
this._setSliderWidth()
this._initSlider()
this._initDots()
},)
},
methods:{
_setSliderWidth(){
this.children = this.$refs.sliderGroup.children let width =
let sliderWidth = this.$refs.slider.clientWidth
for (let i = ; i < this.children.length;i++){
let child = this.children[i]
addClass(child,'slider-item') child.style.width = sliderWidth + 'px'
width += sliderWidth
}
if(this.loop){
width += * sliderWidth
}
this.$refs.sliderGroup.style.width = width + 'px'
},
_initDots() {
this.dots = new Array(this.children.length-)
},
_initSlider(){
this.slider = new BScroll(this.$refs.slider,{
scrollX:true,
scrollY:false,
momentum:false,
snap:true,
snapLoop:this.loop,
snapThreshold:0.3,
snapSpeed:,
click:true
} )
}
}
}
</script> <style scoped lang="stylus" rel="stylesheet/stylus">
@import "~common/stylus/variable" .slider
min-height: 1px
.slider-group
position: relative
overflow: hidden
white-space: nowrap
.slider-item
float: left
box-sizing: border-box
overflow: hidden
text-align: center
a
display: block
width: %
overflow: hidden
text-decoration: none
img
display: block
width: %
.dots
position: absolute
right:
left:
bottom: 12px
text-align: center
font-size:
.dot
display: inline-block
margin: 4px
width: 8px
height: 8px
border-radius: %
background: $color-text-l
&.active
width: 20px
border-radius: 5px
background: $color-text-ll
</style>
slider.vue
将轮播图当前页与小圆圈绑定样式
<div class="dots">
<span class="dot" v-for = '(item,index) in dots' :class="{active: currentPageIndex === index}">
</span>
</div>
index--->索引当前第几个元素
添加样式active
:class="{active: currentPageIndex === index}">
currentPageIndex:标识当前页数
需要先在data() 方法里面初始化currentPageIndex export default{
data(){
return {
dots:[],
// 标识当前页数
currentPageIndex:
}
}, 到索引的页面就添加active类
当前对象。也就是指.dot
当dot是active的时候,就添加样式
维护currentPageIndex
currentPageIndex什么时候切换的?如何将滚动到的页面与currentPageIndex结合? 当初始化slider的时候,绑定事件 // 当滚动到下一张会触发scrollEnd事件
scrollEnd事件会派发一个回调函数
this.slider.on('scrollEnd', ()=>{
// 获取当前 getCurrentPage()为slider的方法 返回的对象有个pageX方法
pageX--->当前第几个元素
let pageIndex = this.slider.getCurrentPage().pageX
if (this.loop) {
pageIndex -=
//再循环模式下,会默认在第一个元素添加一个拷贝 所以要减1
}
this.currentPageIndex = pageIndex
})
这里我们用到了 Vue 的特殊元素—— slot 插槽,它可以满足我们灵活定制列表 DOM 结构的需求。接下来我们来看看 JS 部分:
<script type="text/ecmascript-6">
import BScroll from 'better-scroll'
export default {
props: {
/** * 1 滚动的时候会派发scroll事件,会截流。
* 2 滚动的时候实时派发scroll事件,不会截流。
* 3 除了实时派发scroll事件,在swipe的情况下仍然能实时派发scroll事件
*/
probeType: {
type: Number,
default:
},
/**
* 点击列表是否派发click事件
*/
click: {
type: Boolean,
default: true
},
/** * 是否开启横向滚动 */
scrollX: {
type: Boolean,
default: false
},
/** * 是否派发滚动事件 */
listenScroll: {
type: Boolean,
default: false
},
/** * 列表的数据 */
data: {
type: Array,
default: null
},
/** * 是否派发滚动到底部的事件,用于上拉加载 */
pullup: {
type: Boolean,
default: false
},
/** * 是否派发顶部下拉的事件,用于下拉刷新 */
pulldown: {
type: Boolean,
default: false
},
/** * 是否派发列表滚动开始的事件 */
beforeScroll: {
type: Boolean,
default: false
},
/** * 当数据更新后,刷新scroll的延时。 */
refreshDelay: {
type: Number,
default: }
},
mounted() {
// 保证在DOM渲染完毕后初始化better-scroll
setTimeout(() => {
this._initScroll()
}, )
},
methods: {
_initScroll() {
if (!this.$refs.wrapper) {
return
}
// better-scroll的初始化
this.scroll = new BScroll(this.$refs.wrapper, {
probeType: this.probeType,
click: this.click,
scrollX: this.scrollX
})
// 是否派发滚动事件
if (this.listenScroll) {
let me = this this.scroll.on('scroll', (pos) => {
me.$emit('scroll', pos)
})
}
// 是否派发滚动到底部事件,用于上拉加载
if (this.pullup) {
this.scroll.on('scrollEnd', () => {
// 滚动到底部
if (this.scroll.y <= (this.scroll.maxScrollY + )) {
this.$emit('scrollToEnd')
}
})
}
// 是否派发顶部下拉事件,用于下拉刷新
if (this.pulldown) {
this.scroll.on('touchend', (pos) => {
// 下拉动作
if (pos.y > ) {
this.$emit('pulldown')
}
})
}
// 是否派发列表滚动开始的事件
if (this.beforeScroll) {
this.scroll.on('beforeScrollStart', () => {
this.$emit('beforeScroll')
})
}
},
disable() {
// 代理better-scroll的disable方法
this.scroll && this.scroll.disable()
},
enable() {
// 代理better-scroll的enable方法
this.scroll && this.scroll.enable()
},
refresh() {
// 代理better-scroll的refresh方法
this.scroll && this.scroll.refresh()
},
scrollTo() {
// 代理better-scroll的scrollTo方法
this.scroll && this.scroll.scrollTo.apply(this.scroll,
arguments)
},
scrollToElement() {
// 代理better-scroll的scrollToElement方法
this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments)
}
},
watch: {
// 监听数据的变化,延时refreshDelay时间后调用refresh方法重新计算,保证滚动效果正常
data() {
setTimeout(() => {
this.refresh()
}, this.refreshDelay)
}
}
}
</script>
JS 部分实际上就是对 better-scroll 做一层 Vue 的封装,通过 props 的形式,
把一些对 better-scroll 定制化的控制权交给父组件;
通过 methods 暴露的一些方法对 better-scroll 的方法做一层代理;
通过 watch 传入的 data,当 data 发生改变的时候,
在适当的时机调用 refresh 方法重新计算 better-scroll 确保滚动效果正常,
这里之所以要有一个 refreshDelay 的设置是考虑到如果我们对列表操作用到了 transition-group 做动画效果
,那么 DOM 的渲染完毕时间就是在动画完成之后。 有了这一层 scroll 组件的封装,我们来修改刚刚最复杂的代码(假设我们已经全局注册了 scroll 组件)。
<template>
<scroll class="wrapper"
:data="data"
:pulldown="pulldown"
@pulldown="loadData">
<ul class="content">
<li v-for="item in data">{{item}}</li>
</ul>
<div class="loading-wrapper"></div>
</scroll>
</template>
<script>
import BScroll from 'better-scroll'
export default {
data() {
return {
data: [],
pulldown: true
}
},
created() {
this.loadData()
},
methods: {
loadData() {
requestData().then((res) => {
this.data = res.data.concat(this.data)
})
}
}
}
</script> 可以很明显的看到我们的 JS 部分精简了非常多的代码,没有对 better-scroll 再做命令式的操作了,
同时把数据请求和 better-scroll 也做了剥离,父组件只需要把数据 data 通过 prop 传给 scroll 组件,
就可以保证 scroll 组件的滚动效果。
同时,如果想实现下拉刷新的功能,只需要通过 prop 把 pulldown 设置为 true,
并且监听 pulldown 的事件去做一些数据获取并更新的动作即可,整个逻辑也是非常清晰的。
动态的给子元素设置宽度,当能滑动或者自动轮播的时候,子元素的宽度乘以2,用来切换,因为轮播图想无缝滑动,
必须将第一张图放到最后一个位置,最后一张图放到第一张的位置前面,假如有五个轮播图的话,
事实上,获取的宽度是七张图的宽度。
自动播放
slider.vue
props:{
loop:{
// 循环轮播
type:Boolean,
default: true
},
autoPlay:{
// 自动轮播
ype:Boolean,
default: true
优化:
当屏幕宽度变化的时候,图片错位,而宽度是由sliderWidth控制的
方法: 监听Windows的resizer事件,重新渲染sliderWidth
//监听窗口改变事件
window.addEventListener('resize', () => {
if (!this.slider){
// 初始化的时候直接返回
return
}
// 重新调用计算宽度的方法
this._setSliderWidth(true)
})
},
window窗口改变事件:resize
addEventListener() 方法
用于向指定元素添加事件句柄
element.addEventListener(event, function, useCapture)
参数:
event:
必须。字符串,指定事件名。 注意: 不要使用 "on" 前缀。 例如,使用 "click" ,而不是使用 "onclick" function
必须。指定要事件触发时执行的函数。 当事件对象会作为第一个参数传入函数。 事件对象的类型取决于特定的事件。例如,
"click" 事件属于 MouseEvent(鼠标事件) 对象。 useCapture
可选。布尔值,指定事件是否在捕获或冒泡阶段执行。 可能值: true - 事件句柄在捕获阶段执行
false- false- 默认。事件句柄在冒泡阶段执行
参数
添加标志位,重置过的设置为true
methods:{
// isResize标志位判读是不是重置过来的
_setSliderWidth(isResize){
this.children = this.$refs.sliderGroup.children let width =
let sliderWidth = this.$refs.slider.clientWidth
for (let i = ; i < this.children.length;i++){
let child = this.children[i]
addClass(child,'slider-item') child.style.width = sliderWidth + 'px'
width += sliderWidth
}
// && !isResize
if(this.loop && !isResize){
// 刚开始进来只需要加一次宽度
width += * sliderWidth
}
this.$refs.sliderGroup.style.width = width + 'px'
},
知识点
1:slot---> 插槽
2:使用better-scroll
3:created和mounted
created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
vue music-抓取歌单列表数据(渲染轮播图)的更多相关文章
- Vue实现音乐播放器(七):轮播图组件(二)
轮播图组件 <template> <div class="slider" ref="slider"> <div class=&qu ...
- 05-06 Flutter JSON和序列化反序列化、创建模型类转换Json数据、轮播图数据渲染:Flutter创建商品数据模型 、请求Api接口渲染热门商品 推荐商品
Config.dart class Config{ static String domain='http://jd.itying.com/'; } FocusModel.dart class Focu ...
- 使用 Python 抓取欧洲足球联赛数据
Web Scraping在大数据时代,一切都要用数据来说话,大数据处理的过程一般需要经过以下的几个步骤 数据的采集和获取 数据的清洗,抽取,变形和装载 数据的分析,探索和预测 ...
- H5音乐播放器【歌单列表】
上篇详细描述了播放页歌词如何实现跟随跟单滚动,如何解析歌词,那么歌单页又是如何生成的呢,话不多说,直接上图上代码! 首先需要获取数据,具体获取数据api请转到我跟我大兄弟博客去观看学习去,同时也感谢我 ...
- 抓取Js动态生成数据且以滚动页面方式分页的网页
代码也可以从我的开源项目HtmlExtractor中获取. 当我们在进行数据抓取的时候,如果目标网站是以Js的方式动态生成数据且以滚动页面的方式进行分页,那么我们该如何抓取呢? 如类似今日头条这样的网 ...
- 如何用python抓取js生成的数据 - SegmentFault
如何用python抓取js生成的数据 - SegmentFault 如何用python抓取js生成的数据 1赞 踩 收藏 想写一个爬虫,但是需要抓去的的数据是js生成的,在源代码里看不到,要怎么才能抓 ...
- 如何抓取电商的数据 & Python
如何抓取电商的数据 & Python https://www.zhihu.com/question/40720286 https://www.zhihu.com/question/382455 ...
- Python小爬虫——抓取豆瓣电影Top250数据
python抓取豆瓣电影Top250数据 1.豆瓣地址:https://movie.douban.com/top250?start=25&filter= 2.主要流程是抓取该网址下的Top25 ...
- Fiddler 抓取 app 网络请求数据
通过设置代理在同一个路由器下可以通过 Fiddler 实现抓取 app 的网络数据 步骤如下: 手机(Android ,iOS 都可以)和 PC 连到同一个路由器 对手机连接的 WIFI 设置代理,代 ...
随机推荐
- visio基础教程(一)
- C语言的 32个关键之和9个控制语言之关键字
auto break case char const continue default do double else enum extern float for goto ...
- 从Linux服务器下载文件到本地命令
从Linux服务器下载文件夹到本地1.使用scp命令 scp /home/work/source.txt work@192.168.0.10:/home/work/ #把本地的source.txt文件 ...
- object类之toString方法
object是所有类的基类 如果没有使用extends关键字指明其基类,则默认基类为object类 public class Person{ ........ } 等价于: public class ...
- Ubuntu 16.04 (官方命令行)安装MongoDB 3.6.2(社区版)
概述 使用本教程从 .deb 包在LTS Ubuntu Linux系统上安装MongoDB Community Edition. 虽然Ubuntu包含自己的MongoDB包,但官方的MongoDB社区 ...
- #include <ntifs.h>出现PEPROCESS redefinition问题处理
转载:http://blog.csdn.net/ytfrdfiw/article/details/23334297 如果在自己的程序中,即包含ntddk.h和ntifs.h的时候,编译的时候会出现如下 ...
- 子网掩码与ip有实际关系吗?
子网掩码是作为ip地址的标识,还是本身就是ip地址的一部分?例如10.10.10.1/24和10.10.10.1/25是同一个ip地址吗? 作者:知乎用户链接:https://www.zhihu.co ...
- Uva 12304 - 2D Geometry 110 in 1!
http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...
- sqlplus中文问号
添加两个环境变量后重启. 1.LANG=zh_CN.GBK(GBK是这样形式的,不同编码这里的value值需要跟着改变) 2.NLS_LANG=AMERICAN_AMERICA.ZHS16GBK(这个 ...
- UVA-1343 The Rotation Game (IDA*)
题目大意:数字1,2,3都有八个,求出最少的旋转次数使得图形中间八个数相同.旋转规则:对于每一长行或每一长列,每次旋转就是将数据向头的位置移动一位,头上的数放置到尾部.若次数相同,则找出字典序最小旋转 ...