用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 组件应用 、路由组件异步加载 、 项目部署 。学习