(1.使用router定義跳轉連接,2. 使用axios獲得音樂第三方數據,並渲染到頁面上,3.組件之間傳值(props))html
1.接下來使用了vue-router路由動態傳值,父子嵌套式路由 vue
this.$router.push({
path: `/recommend/${item.id}`
});ios
2.router入口文件定義路由路徑:vue-router
3. 此時須要渲染路由在父組件中:vuex
B.使用vuex進行狀態管理:npm
npm install vuex --save
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex)
![](http://static.javashuo.com/static/loading.gif)
定義一個state,getters,mutations,方便組件中使用:axios
export 導出vuex定義模塊bash
第二欄效果圖:app
主要代碼:
<template> <div > <div class="wrapper" ref='wrapper'> <div class="content"> <listview title="推薦歌單" :showPlayCount="true" :showSinger="false" :limit="6" :resources="recommendList" @select="selectedList"></listview> <listview title="最In音樂" :showPlayCount="false" :showSinger="true" :limit="6" :resources="newList" @select="selectedList"></listview> <listview title="主播電臺" :showPayCount="false" :showSinger="true" :limit="6" :resources="djrecommend" @select="selectedList"></listview> </div> <router-view></router-view> </div> </div> </template> <script> import Listview from '@/components/listview/listview' import {mapGetters, mapMutations} from 'vuex' import store from "@/store/store.js"; export default{ name:"recommend", store, data(){ return { list:null } }, components:{ Listview, }, methods: { //定義selectedList方法,router.push路由跳轉 selectedList(item) { this.$router.push({ path: `/recommend/${item.id}` }); console.log(item); this.setSongList(item); }, ...mapMutations([ 'setSongList' ]) }, created(){ /*this.axios .get('http://localhost:3000/top/playlist/highquality') .then((response)=>{ this.list = response.data.playlists // console.log(this.list) }) .catch((response)=>{ console.log(response) })*/ this.recommendList = 'http://localhost:3000/top/playlist/highquality'; this.newList='http://localhost:3000/top/playlist?order=hot'; this.djrecommend='http://localhost:3000/personalized/djprogram'; } } </script> <style lang="scss" rel="style/scss"> </style>
<template> <transition name="fade"> <music-list :songs="songs" :id="id"> </music-list> </transition> </template> <script> import {mapGetters} from 'vuex'; import musicList from '@/components/music-list/music-list' export default { name: "list-detail", data() { return { songs: {}, id: '' } }, created() { this._getSongList(); }, methods: { _getSongList() { if (!this.songList || !this.songList.id) { this.$router.push('/recommend'); return; } //使用vuex定義的數據獲得父組件的相關值 this.songs = this.songList; this.id = this.songList.id; }, }, computed: { ...mapGetters([ 'songList' ]) }, components: { musicList }, } </script> <style lang="scss"> .fade-enter-active, .fade-leave-active { transition: all 0.3s; } .fade-enter, .fade-leave-to { opacity: 0; } </style>
<template> <div class="music-list"> <div class="header"> <div class="header-img"> <img :src="songs.coverImgUrl"> <div class="play-count"><i class="icon iconfont icon-headset"></i>{{songs.playCount|unitConvert}}</div> <div class="detail-btn"><i class="icon iconfont icon-detail"></i></div> </div> <div class="header-content"> <div class="name">{{songs.name}}</div> <div class="tags" v-show="songs.tags"> <span>標籤: </span><span class="tag" v-for="(tag,idx1) in songs.tags" :key="idx1">{{tag}}</span> </div> <div class="subname" v-if="songs.subscribers && songs.subscribers.length > 0"> {{songs.subscribers[0].nickname}}<span class="create-time">建立於{{songs.createTime}}</span> </div> </div> <div class="back" @click="back"> <i class="icon iconfont icon-close"></i> </div> <div class="background"> <img :src="songs.coverImgUrl"> </div> </div> <div class="body"> <div class="header-bar"> <i class="icon iconfont icon-play"></i><span class="playAll">播放所有<i class="count">(共{{detail.length}}首)</i></span> <span class="collect"><i class="icon iconfont icon-add"></i>收藏({{subscribedCount|unitConvert}})</span> </div> <div class="songList-wrapper" ref="listWrapper"> <ul class="songlist"> <li class="song-item" v-for="(item, idx) in detail" :key="idx" @click="selectItem(item, idx, $event)"> <div class="line-number"> <span>{{idx+1}}</span> </div> <div class="item-content"> <div class="songname">{{item.name}}</div> <div class="songer">{{item.ar[0].name}} - {{item.al.name}}</div> </div> <div class="tool"> <i class="icon iconfont icon-tool"></i> </div> </li> </ul> </div> </div> </div> </template> <script> import {unitConvert} from '@/common/js/unitConvert' import {mapGetters, mapActions} from 'vuex' export default { name: "music-list", //獲得list-detail傳過來的id,並獲取第三方數據,渲染到頁面中 props: { songs: { type: Object }, id: { type: [String, Number] } }, data() { return { detail: [], subscribedCount: '' } }, created() { if (this.id) { let url = `http://localhost:3000/playlist/detail?id=${this.id}`; this.axios.get(url).then((res) => { this.detail = res.data.playlist.tracks; this.subscribedCount = res.data.playlist.subscribedCount; }) } }, methods: { back(){ }, ...mapActions([ 'selectPlay' ]) }, filters: { unitConvert(num) { return unitConvert(num); } } } </script> <style lang="scss"> @function px2rem($px) { @return $px / 30 + rem; } .music-list { position: fixed; z-index: 200; top: 0; bottom: 0; left: 0; right: 0; background: #fff; .header { position: relative; display: flex; width: 100%; height: px2rem(400); align-items: center; overflow: hidden; background-color: rgba(0, 0, 0, 0.2); .header-img { display: flex; position: relative; justify-content: center; flex: 0 0 px2rem(300); width: px2rem(300); height: px2rem(250); img { width: px2rem(250); height: px2rem(250); } .play-count { position: absolute; top: 0; right: px2rem(40); color: #fff; font-size: px2rem(24); font-weight: bold; .icon-headset { color: #fff; font-size: px2rem(24); font-weight: bold; margin-right: px2rem(8); } } .detail-btn { position: absolute; bottom: 0; right: px2rem(42); color: #fff; .icon-detail { font-size: px2rem(36); font-weight: bold; } } } .header-content { flex: 1; height: px2rem(250); padding-right: px2rem(25); color: #fff; .name { margin: px2rem(20) 0; height: px2rem(90); font-size: px2rem(32); font-weight: bold; } .tags { margin-bottom: px2rem(24); font-size: px2rem(26); line-height: px2rem(26); height: px2rem(26); .tag { padding: 0 px2rem(12); border: 2px solid #fff; border-radius: px2rem(8); margin-left: px2rem(12); } } .subname { font-size: px2rem(26); line-height: px2rem(26); height: px2rem(26); .create-time { margin-left: px2rem(10); } } } .icon-close { position: absolute; top: 0; right: px2rem(16); padding: px2rem(20); color: #fff; font-size: px2rem(32); font-weight: bold; } .background { position: absolute; top: 0; left: 0; width: 100%; height: px2rem(400); z-index: -1; filter: blur(px2rem(100)); overflow: hidden; } } .body { .header-bar { display: flex; line-height: px2rem(80); height: px2rem(80); border-bottom: 1px solid #eee; justify-content: center; text-align: center; .icon-play { width: px2rem(80); font-size: px2rem(48); } .playAll { flex: 1; font-size: px2rem(26); text-align: left; .count { font-size: px2rem(24); font-style: normal; color: #7e8c8d; } } .collect { padding: 0 px2rem(24); background: #F93021; color: #fff; font-size: px2rem(26); font-weight: bold; text-align: center; .icon-add { font-size: px2rem(26); color: #fff; font-weight: bold; } } } .songList-wrapper { position: absolute; top: px2rem(480); bottom: 0; left: 0; width: 100%; overflow: hidden; .songlist { background: #fff; .song-item { display: flex; &.list-complete-enter-active, &.list-complete-leave-active { transition: all 0.2s linear; } &.list-complete-enter, &.list-complete-leave-to { opacity: 0; transform: translateY(px2rem(30)); } .line-number { flex: 0 0 px2rem(80); width: px2rem(80); height: px2rem(80); line-height: px2rem(80); text-align: center; font-size: px2rem(30); color: #7e8c8d; } .item-content { flex: 1; border-bottom: 1px solid #eee; width: 80%; .songname { font-size: px2rem(28); overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } .songer { font-size: px2rem(22); color: #7e8c8d; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } } .tool { flex: 0 0 px2rem(80); width: px2rem(80); line-height: px2rem(80); border-bottom: 1px solid #eee; text-align: center; .icon-tool { font-size: px2rem(30); } } } } } } } </style>
router的相關定義:
import Vue from 'vue'
import Router from 'vue-router'
import Helloworld from '@/components/HelloWorld'
import Recommend from '@/page/recommend'
import HotRecommend from '@/page/hotrecommend'
import Search from '@/page/search'
//引入子組件
import recommendList from '@/page/list-detail'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
component: Helloworld
},
{
path: '/recommend',
component: Recommend,
//子組件路由
children: [
{
path: ':id',
component: recommendList
}
]
},
{
path: '/Hotrecommend',
component: HotRecommend
},
{
path: '/search',
component: Search
}
]
})
vuex-- store.js設定:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex)
const state = {
// count:1,
songList:null
}
const getters = {
songList:function(state) {
return state.songList;
}
}
const mutations = {
/*increment(state){
state.count++
},
decrement(state){
state.count--
},*/
setSongList(state,item) {
state.songList=item;
}
}
const actions={
/*increment: ({commit})=>{
commit('increment')
},
decrement: ({commit})=>{
commit('decrement')
},*/
/* selectPlay: ({commit, state}, {list, index})=>{
commit('setPlayList',list)
},
*/
}
export default new Vuex.Store({
state,
mutations,
getters,
actions
})