用Vue3.0开发音乐Web app(视频源码齐)去网盘学习啦

446 阅读1分钟

用Vue3.0开发音乐Web app

Vue3.0高阶实战:开发高质量音乐Web app vx(cmL46679910)

第5章的学习内容如下:(视频资源vx( cmL46679910 **))**播放器基础样式及歌曲播放功能开发 、

<script>
  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.disp**(视频资源vx(** cmL46679910 **))**atch('clearSongList')
        hide()
      }

      function showAddSong() {
        addSongRef.value.show()
      }
    }
  }
</script>

播放器播放按钮的暂停与播放逻辑开发、播放器歌曲前进与后退逻辑开发 、播放器 DOM 异常错误处理、播放器 歌曲播放模式相关逻辑开发 、

image.png 播放器 歌曲收藏功能相关逻辑开发(1)、播放器 歌曲收藏功能相关逻辑开发(2)、播放器 进度条相关逻辑开发、 播放器 进度条相关逻辑开发**(视频资源vx(** cmL46679910 ))(下)、播放器 cd 唱片旋转相关逻辑开发 、 播放器 歌词相关逻辑开发(01) 、播放器 歌词相关逻辑开发(02)、播放器 歌词相关逻辑开(03)、播放器

  export default {
    name: 'tab',
    data() {
      return {
        tabs: [
          {
            name: '推荐',
            path: '/recommend'
          },
          {
            name: '歌手',
            path: '/singer'
          },
          {
            name: '排行',
            path: '/top-list'
          },
          {
            name: '搜索',
            path: '/search'
  }
</script>

中间视图层手指交互相关逻辑开发(上)、播放器 中间视图层手指交互相关逻辑开发(下)、播放器 mini 播放器开发(01)、播放器 mini 播放器开发(02)、播放器 mini 播放器开(03)、播放器 mini 播放器开发(04)、播放器 全屏切换过渡效果实现(上)、播放器 全屏切换过渡效果实现(下)、播放器 播放列表组件实现(01)、播放器 播放列表组件实现(02)、播放器播放列表组件实现(03)、播放器 播放列表组件实现(04)、播放器 播放列表组件实现(05)、播放器滚动列表高度自适应、播放器高阶Scroll 组件的实现 。

第6章的学习内容如下: 歌单详情页开发(上)、歌单详情页开发(下)、排行榜页面开发、排行榜详情页开发(上)、排行榜详情页开发(下)。

  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) 、

  export default {
    name: 'tab',
    data() {
      return {
        tabs: [
          {
            name: '推荐',
            path: '/recommend'
          },
          {
            name: '歌手',
            path: '/singer'
          },
          {
            name: '排行',
            path: '/top-list'
          },
          {
            name: '搜索',
            path: '/search'
          }
        ]
      }
    }
  }
</script>

搜索页面 Suggest 组件开发(03)、搜索页面 Suggest 组件开发(04)、搜索页面 Suggest 组件开发(05)、搜索页面Suggest组件开发(06)、(视频资源vx( cmL46679910 )) 搜索页面 Suggest 组件开发、搜索页面搜索历史功能开发(01)、搜索页面搜索历史功能开发(02)、搜索页面搜索历史功能开发(03)、搜索页面搜索历史功能开发(04) 。

  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) 、(视频资源vx( cmL46679910 )) 添加歌曲到列表功能开发(05)、用户中心页面开发(01)、用户中心页面开发(02)、用户中心页面开发(03)。

  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章的学习内容如下: keep-alive 组件应用 、路由组件异步加载 、 项目部署 。