用Vue3.0開發音樂Web appjavascript
Vue3.0高階實戰:開發高質量音樂Web app vx(cmL46679910)css
第5章的學習內容以下:播放器基礎樣式及歌曲播放功能開發 、播放器播放按鈕的暫停與播放邏輯開發 、vue
<script> import Scroll from '@/components/base/scroll/scroll' import Confirm from '@/components/base/confirm/confirm' import AddSong from '@/components/add-song/add-song' import { ref, computed, nextTick, watch } from 'vue' import { useStore } from 'vuex' import useMode from './use-mode' import useFavorite from './use-favorite' export default { name: 'playlist', components: { AddSong, Confirm, Scroll }, setup() { const visible = ref(false) const removing = ref(false) const scrollRef = ref(null) const listRef = ref(null) const confirmRef = ref(null) const addSongRef = ref(null) const store = useStore() const playlist = computed(() => store.state.playlist) const sequenceList = computed(() => store.state.sequenceList) const currentSong = computed(() => store.getters.currentSong) const { modeIcon, modeText, changeMode } = useMode() const { getFavoriteIcon, toggleFavorite } = useFavorite() watch(currentSong, async (newSong) => { if (!visible.value || !newSong.id) { return } await nextTick() scrollToCurrent() }) function getCurrentIcon(song) { if (song.id === currentSong.value.id) { return 'icon-play' } } async function show() { visible.value = true await nextTick() refreshScroll() scrollToCurrent() } function hide() { visible.value = false } function selectItem(song) { const index = playlist.value.findIndex((item) => { return song.id === item.id }) store.commit('setCurrentIndex', index) store.commit('setPlayingState', true) } function refreshScroll() { scrollRef.value.scroll.refresh() } function scrollToCurrent() { const index = sequenceList.value.findIndex((song) => { return currentSong.value.id === song.id }) if (index === -1) { return } const target = listRef.value.$el.children[index] scrollRef.value.scroll.scrollToElement(target, 300) } function removeSong(song) { if (removing.value) { return } removing.value = true store.dispatch('removeSong', song) if (!playlist.value.length) { hide() } setTimeout(() => { removing.value = false }, 300) } function showConfirm() { confirmRef.value.show() } function confirmClear() { store.dispatch('clearSongList') hide() } function showAddSong() { addSongRef.value.show() } return { visible, removing, scrollRef, listRef, confirmRef, addSongRef, playlist, sequenceList, getCurrentIcon, show, hide, selectItem, removeSong, showConfirm, confirmClear, showAddSong, // mode modeIcon, modeText, changeMode, // favorite getFavoriteIcon, toggleFavorite } } } </script>
播放器歌曲前進與後退邏輯開發 、 播放器 DOM 異常錯誤處理 、(視頻資源vx(cmL46679910)) java
播放器 歌曲播放模式相關邏輯開發 、 播放器 歌曲收藏功能相關邏輯開發(1) 、 播放器 歌曲收藏功能相關邏輯開發(2)、 播放器 進度條相關邏輯開發、 播放器 進度條相關邏輯開發(下) 、 播放器 cd 唱片旋轉相關邏輯開發 、 播放器 歌詞相關邏輯開發(01) 、 播放器 歌詞相關邏輯開發(02) 、vuex
script> export default { name: 'tab', data() { return { tabs: [ { name: '推薦', path: '/recommend' }, { name: '歌手', path: '/singer' }, { name: '排行', path: '/top-list' }, { name: '搜索', path: '/search' </script>
播放器 歌詞相關邏輯開發(03)、播放器 中間視圖層手指交互相關邏輯開發(上) 、播放器 中間視圖層手指交互相關邏輯開發(下) 、播放器 mini 播放器開發(01) 、 播放器 mini 播放器開發(02) 、播放器 mini 播放器開發(視頻資源vx(cmL46679910))(03)、 播放器 mini 播放器開發(04)、 播放器 全屏切換過渡效果實現(上) 、播放器 全屏切換過渡效果實現(下) 、播放器 播放列表組件實現(01)、播放器 播放列表組件實現(02)、 播放器 播放列表組件實現(03) 、 播放器 播放列表組件實現(04) 、 播放器 播放列表組件實現(05)、 播放器 滾動列表高度自適應、播放器 高階 Scroll 組件的實現 。app
第6章 的學習內容以下: 歌單詳情頁開發(上) 、歌單詳情頁開發(下)、排行榜頁面開發 、排行榜詳情頁開發(上) 、 排行榜詳情頁開發(下).異步
<script> export default { name: 'suggest', props: { query: String, showSinger: { type: Boolean, default: true } }, emits: ['select-song', 'select-singer'], setup(props, { emit }) { const singer = ref(null) const songs = ref([]) const hasMore = ref(true) const page = ref(1) const loadingText = ref('') const noResultText = ref('抱歉,暫無搜索結果') const manualLoading = ref(false) const loading = computed(() => { return !singer.value && !songs.value.length }) const noResult = computed(() => { return !singer.value && !songs.value.length && !hasMore.value }) const pullUpLoading = computed(() => { return isPullUpLoad.value && hasMore.value }) const preventPullUpLoad = computed(() => { return loading.value || manualLoading.value }) const { isPullUpLoad, rootRef, scroll } = usePullUpLoad(searchMore, preventPullUpLoad) watch(() => props.query, async (newQuery) => { if (!newQuery) { return } await searchFirst() }) async function searchFirst() { if (!props.query) { return } page.value = 1 songs.value = [] singer.value = null hasMore.value = true const result = await search(props.query, page.value, props.showSinger) songs.value = await processSongs(result.songs) singer.value = result.singer hasMore.value = result.hasMore await nextTick() await makeItScrollable() } async function searchMore() { if (!hasMore.value || !props.query) { return } page.value++ const result = await search(props.query, page.value, props.showSinger) songs.value = songs.value.concat(await processSongs(result.songs)) hasMore.value = result.hasMore await nextTick() await makeItScrollable() } async function makeItScrollable() { if (scroll.value.maxScrollY >= -1) { manualLoading.value = true await searchMore() manualLoading.value = false } } function selectSong(song) { emit('select-song', song) } function selectSinger(singer) { emit('select-singer', singer) } } } </script>
第7章的學習內容以下:搜索頁面搜索框開發、搜索頁面熱門搜索開發、 搜索頁面 Suggest 組件開發(01) 、搜索頁面 Suggest 組件開發(02) 、搜索頁面 Suggest 組件開發(03)、 搜索頁面 Suggest 組件開發(04)、(視頻資源vx(cmL46679910))搜索頁面 Suggest 組件開發(05) 、 搜索頁面 Suggest 組件開發(06)、 搜索頁面 Suggest 組件開發、 搜索頁面搜索歷史功能開發(01) 、 搜索頁面搜索歷史功能開發(02)、搜索頁面搜索歷史功能開發(03)、搜索頁面搜索歷史功能開發(04) 。async
<script> import { debounce } from 'throttle-debounce' export default { name: 'search-input', props: { modelValue: String, placeholder: { type: String, default: '搜索歌曲、歌手' } }, data() { return { query: this.modelValue } }, created() { this.$watch('query', debounce(300, (newQuery) => { this.$emit('update:modelValue', newQuery.trim()) })) this.$watch('modelValue', (newVal) => { this.query = newVal }) }, methods: { clear() { this.query = '' } } } </script> <style lang="scss" scoped> .search-input { display: flex; align-items: center; box-sizing: border-box; width: 100%; padding: 0 6px; height: 32px; background: $color-highlight-background; border-radius: 6px; .icon-search { font-size: 24px; color: $color-text-d; } .input-inner { flex: 1; margin: 0 5px; line-height: 18px; background: $color-highlight-background; color: $color-text; font-size: $font-size-medium; outline: 0; &::placeholder { color: $color-text-d; } } .icon-dismiss { font-size: 16px; color: $color-text-d; } } </style>
第8章 的學習內容以下: 添加歌曲到列表功能開發(01)、添加歌曲到列表功能開發(02) 、添加歌曲到列表功能開發(03) 、添加歌曲到列表功能開發(04) 、
添加歌曲到列表功能開發(05)、用戶中心頁面開發(01)、用戶中心頁面開發(02)、用戶中心頁面開發(03)。ide
export default { name: 'add-song', components: { SearchInput, Suggest, Switches, Scroll, SongList, SearchList, Message }, setup() { const visible = ref(false) const query = ref('') const currentIndex = ref(0) const scrollRef = ref(null) const messageRef = ref(null) const store = useStore() const searchHistory = computed(() => store.state.searchHistory) const playHistory = computed(() => store.state.playHistory) const { saveSearch } = useSearchHistory() watch(query, async () => { await nextTick() refreshScroll() }) async function show() { visible.value = true await nextTick() refreshScroll() } function hide() { visible.value = false } function refreshScroll() { scrollRef.value.scroll.refresh() } function addQuery(s) { query.value = s } function selectSongBySongList({ song }) { addSong(song) } function selectSongBySuggest(song) { addSong(song) saveSearch(query.value) } function addSong(song) { store.dispatch('addSong', song) showMessage() } function showMessage() { messageRef.value.show() }
第9章 的學習內容以下: vx(cmL46679910)keep-alive 組件應用 、路由組件異步加載 、 項目部署 。學習