参考:Framework7+Vue.js Spotify播放器 - 实例详解(1)
Framework7+Vue.js Spotify播放器 - 实例详解(2)
回顾一下:
- 用Template模板初始化
- 添加 Font Awesome Icon 图标库
- Framework7 View和Page概念
- 更新main视图
- 自定义样式文件CSS
- 初始化App应用,关联slider和显示的数值
- 调用Spotify API,处理返回数据
- 新的List页面(搜索结果)
9. media页面(歌曲详情)
当我们点击搜索结果里某一首歌曲,需要打开歌曲详情页面,并且能够播放
新建media.vue:
- 添加组件props: ['mediaId']。动态路由,以歌曲Id为索引,会自动添加到props里,这样详情页面就知道需要展示哪首歌曲了
- 组件mounted时,引入store.searchTracks
- 数据访问:searchTracks[mediaId]
- 本页面不需要工具栏,设置page.no-toolbar
- <audio>是HTML5自带的音频播放元素,后面在Android设备上播放,需要替换成Media.plugin
# \spotifyApp\src\assets\vue\Media.vue
<template>
<f7-page name="media" no-toolbar id="media">
<f7-navbar>
<f7-nav-left back-link="Back" sliding></f7-nav-left>
<f7-nav-center sliding>Media Detail</f7-nav-center>
<f7-nav-right>
<f7-link icon="icon-bars" open-panel=""></f7-link>
</f7-nav-right>
</f7-navbar>
<f7-block-title>Track Info</f7-block-title>
<f7-list>
<f7-list-item :media="'![]( + searchTracks[mediaId].album.images[1].url +)'" :title="searchTracks[mediaId].name">
</f7-list-item>
<f7-list-item>
<f7-label>Type</f7-label>
<f7-label>{{searchTracks[mediaId].type}}</f7-label>
</f7-list-item>
<f7-list-item>
<f7-label>Artist</f7-label>
<f7-label>{{searchTracks[mediaId].artists[0].name}}</f7-label>
</f7-list-item>
</f7-list>
<f7-block-title>Album Info</f7-block-title>
<f7-list form>
<f7-list-item title="">
<f7-label>Album</f7-label>
<f7-label>{{searchTracks[mediaId].album.name}}</f7-label>
</f7-list-item>
<f7-list-item>
<f7-label>Popularity Rank</f7-label>
<f7-input type="range" min="0" max="100" step="1" v-model="sliderVal" disabled/>
<f7-input type="text" disabled value="90" class="rangeVal" />
</f7-list-item>
</f7-list>
<f7-block-title>Preview</f7-block-title>
<f7-block inset>
<f7-block inner>
<div id="previewAudio" align="center">
<audio controls preload :src="searchTracks[mediaId].preview_url"></audio>
</div>
</f7-block>
</f7-block>
<f7-list>
<f7-list-item class="bottom">
<a href="#" class="item-media link favorite"><i class="icon fa fa-star fa-2x"></i> </a>
<div class="item-title">
<a :href="searchTracks[mediaId].external_urls.spotify" class="link external">Open in Spotify</a>
</div>
<a href="#" class="share item-media link"><i class="icon fa fa-external-link fa-2x"></i></a>
</f7-list-item>
</f7-list>
</f7-page>
</template>
<script>
import store from '../../store.js'
export default {
name: 'list',
props: ['mediaId'], // <!-- $route.params are also passed as component props: -->
data() {
return {
searchTracks: [],
}
},
mounted() {
this.searchTracks = store.searchTracks;
}
}
</script>
Media.vue添加到路由:
# \spotifyApp\src\routes.js
export default [
{
path: '/list/',
component: require('./assets/vue/List.vue')
},
{
path: '/media/:mediaId/',
component: require('./assets/vue/Media.vue')
}
]
List.vue里,以路由名+Index访问就行,实际运行时就像/media/0/、/media/1/、/media/2/
:
# \spotifyApp\src\assets\vue\List.vue
<f7-list-item swipeout v-for="(item, index) in searchTracks" :key="item.id"
:link="'/media/'+index+'/'" :media="'![]( + item.album.images[2].url +)'" :title="item.name" :subtitle="item.artists[0].name" :text="item.album.name">
为了页面美观,main.css里作了一些小调整:
# \spotifyApp\src\assets\css\main.css
.statusbar-overlay {
background: #000000;
}
i.icon.icon-spotify {
width: 29px;
height: 29px;
background-image: url("../images/spotify.png");
margin-right: 3px;
}
/* Item View bottom action buttons */
li.bottom {
position: fixed;
bottom: 0px;
width: 100%;
}
/* Add space before actual range val */
.rangeVal {
padding-left: 5px;
}
.list-block {
margin: 10px 0 !important;
}
/* Format content headers */
.content-block-title {
margin: 18px 15px 10px;
}
/* Format the long track titles */
.list-block .item-title {
white-space: inherit;
position: relative;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
/* Formats the Popularity Rank title to display slider better */
.list-block .item-title.label {
width: 50%;
}
img.detail {
max-width: 100%;
}
.list-block .item-media {
flex-shrink: 1;
}
到此,你的页面应该像这样:
10. 更多Mobile App元素:侧边栏Sidebar和元素左滑右滑Swipeout
手机应用,都会用到这种侧边栏Sidebar:
很简单,在main.vue里添加side panel:
- f7-panel:定义在f7-views之外,因为是全局共享的,子页面也需要打开Sidebar
- f7-panel left reveal:定义在左侧出现,reveal是不覆盖原页面内容。如果需要覆盖效果,使用cover就行
- 打开sidebar:F7已经默认写好了,使用
<f7-link icon="icon-bars" open-panel="left"></f7-link>
就行,简单吧? - 关闭sidebar:点击侧边栏外面,就自动关闭了。当然,你也可以添加按钮,手动触发关闭事件
- @click,methods: {} 对于选项,添加点击事件处理就行。
- TODO:点击About,打开“about.vue”页面,你来试一试吧!
# \spotifyApp\src\main.vue
<template>
<!-- App -->
<div id="app">
<!-- Statusbar -->
<f7-statusbar></f7-statusbar>
<!-- Left Panel -->
<f7-panel left reveal layout="dark">
<f7-view id="left-panel-view" navbar-through :dynamic-navbar="true">
<f7-navbar title="Left Panel"></f7-navbar>
<f7-pages>
<f7-page>
<f7-list>
<f7-list-item media="<i class='icon fa fa-cog'></i>" @click="onSetting" title="Settings">
</f7-list-item>
<f7-list-item media="<i class='icon fa fa-star'></i>" @click="onFavorite" title="Favorites">
</f7-list-item>
<f7-list-item media="<i class='icon fa fa-info-circle'></i>" @click="onAbout" title="About">
</f7-list-item>
</f7-list>
</f7-page>
</f7-pages>
</f7-view>
</f7-panel>
<f7-views>
<!-- Main view-->
<f7-view main :dynamicNavbar="true">
<!-- Top Navigation Bar-->
<f7-navbar>
<f7-nav-left>
<f7-link icon="icon-bars" open-panel="left"></f7-link>
</f7-nav-left>
<f7-nav-center>Spotify Browser</f7-nav-center>
</f7-navbar>
<!-- Pages -->
<f7-pages navbar-through toolbar-through>
。。。
iPhone手机,大家有过体验,比如短信左滑,就会出现“删除”的快捷按键,很方便。前面我们已经实现了左滑、右滑效果,现在来添加具体的Swipeout功能:
修改List.vue,监听@click事件
- @click="addFavorite(index)":带入index参数,知道添加哪首歌到收藏夹
- favoriteList:添加到store.js。这样,共享收藏夹数据给其它组件,比如sidebar
# \spotifyApp\src\store.js
const store = {
searchTracks: [],
favoriteList: [],
};
export default store;
- preview(index):调用了Phonegap Media插件,需要手动安装:
$ phonegap plugin add cordova-plugin-media --save
。左滑后,点击Preview,会预览播放7秒钟 - share(index):调用手机原生的分享功能,后续会实现
Swipeout在浏览器上体验跟手机上略有不同,建议通过Phoegap Developer手机App来测试。参考://www.greatytc.com/p/c24086ac57ba
# \spotifyApp\src\assets\vue\List.vue
...
<f7-list class="searchbar-found" media-list id="mediaList">
<f7-list-item swipeout v-for="(item, index) in searchTracks" :key="item.id" :link="'/media/'+index+'/'" :media="'![]( + item.album.images[2].url +)'" :title="item.name" :subtitle="'<span class=singerPrex>by </span>'+item.artists[0].name" :text="item.album.name">
<f7-swipeout-actions right>
<f7-swipeout-button class="bg-orange">
<a class="bg-orange favorite" @click="addFavorite(index)"><i class="icon fa fa-star fa-2x"></i></a>
</f7-swipeout-button>
<f7-swipeout-button class="bg-blue">
<a href="#" class="bg-blue share" @click="share(index)"><i class="icon fa fa-share fa-2x"></i></a>
</f7-swipeout-button>
</f7-swipeout-actions>
<f7-swipeout-actions left>
<f7-swipeout-button class="bg-green">
<a href="#" class="bg-green preview" @click="preview(index)"><i class="icon fa fa-play fa-2x"></i></a>
</f7-swipeout-button>
</f7-swipeout-actions>
</f7-list-item>
</f7-list>
...
<script>
import store from '../../store.js'
export default {
name: 'list',
data() {
return {
searchTracks: [],
favoriteList: [],
}
},
mounted() {
window.Dom7(document).on('deviceready', () => {
console.log("List Page is ready!");
this.searchTracks = store.searchTracks;
this.favoriteList = store.favoriteList;
});
},
methods: {
addFavorite(index) {
store.favoriteList.push(this.searchTracks[index]);
window.f7.alert(this.searchTracks[index].name + ' added to favorites!');
},
preview(index) {
var item = this.searchTracks[index];
window.f7.alert("Previewing " + item.name);
var media = new Media(item.preview_url, function() {
console.log("Media Success");
}, function(error) {
console.log("Media fail " + error)
}, null);
media.play();
setTimeout(function() {
media.stop()
}, 7000) //preview for 7 seconds
},
share(index) {
window.f7.alert(this.searchTracks[index].name + ' shared to...');
}
}
}
</script>
11. 让你的App更有原生体验
--> 请看详解(4)