头图

Preface

Preface

Hello, everyone. I am "The wind does not know the way." If you read this series for the first time, please click . Friends who are learning React can clone this project, refer to learning, and try to do some small functions. Let's start to finish this series. The music players ▶ needs to be completed as follows↓;

Project preview and source code

Recently updated

Update function

  • Login function:

    • For the time being, only "163 mailbox" or "mobile phone number" login is supported
    • Daily recommended playlist (you can view it only if you log in successfully)
    • Personal Homepage & Favorite Playlist & Comment Songs & Like Songs Comment & Create Playlist
  • Local storage song list:

    • Regardless of whether the browser is refreshed afterwards, it will be persistently stored as long as it is in the song list
    • (Refresh the browser, the song list still exists)
  • Song list:

    • Support drag and drop sorting of the song list, and change the playback order
  • Search music box:

    • Optimized to support the keyboard "↑"+"↓" to switch search song content when searching for songs
  • Head progress bar:

    • "Add header progress bar" is displayed when page routing jump & network request
  • 404 page:

    • Add a 404 page, when the route does not match the page, the 404 page will be displayed

Modify BUG&ToDoList

Click to view 👉 Recent optimization and adjustment

Click to view 👉 TO-DO-LIST

Interface function display (new development)

Song search (↑↓ selection)

Support drag and drop sorting of the song list

Login demo

Daily recommendation

image-20210530083650349

Homepage

image-20210530083718485

Music list

Now start to complete this section (a little more complicated), the song list playback component, supporting functions are as follows:

  • Support click on an item to play the song
  • Lyrics scroll in real time
  • Mutually exclusive effect with the lyrics component on the homepage
  • Clear all songs
  • Drag to change order

1. Page layout construction

  1. Page layout construction

  1. Click the button to show and hide (playlist) and add transition effects

  1. It is mutually exclusive with the lyrics display control. (Lyrics list display, turn off lyrics display)

  1. Conten content build

  1. Click on an item to play the corresponding music, and the background is highlighted

    • After clicking the current item, will id transfer function, according to id distributed action , request information Playlist details
    • Pass the play music function to the child component
    • Realize when the music playback ends or manually click the previous song or the next song:

      • Corresponding to item background highlight and then switch (according to redux currentSongIndex )

  1. Click the delete button to prevent the event from bubbling and clear the click-to-play song
  2. Click the clear all button to clear all music and play the next music

2. Lyrics highlighting effect

Lyrics interface

3. Lyrics scrolling effect

  • According to the index currently playing lyrics, the scrolling effect is realized
  • Get DOM , calculate scrollTop , realize scrolling

Music list drag and drop sortablejs sortablejs

Description

  • <font color='red'> When you need to drag and drop the rows or columns of certain tables </font>

    • Not limited to forms
    • As long as it is a row you want to drag

Use drag and drop to sort steps

  1. installation
npm install sortablejs --save
yarn add sortablejs
  1. Import
import Sortable from 'sortablejs';
  1. Configuration parameter
import React, { useRef } from 'react';

// other hook
const playlistRef = useRef();// 用于获取DOM元素

useEffect(() => {
  // 获取列表项父元素
  const el = playlistRef.current.querySelector('.main-playlist');
  new Sortable(el, {
    sort: true,
    animation: 200,
    onEnd: function (evt) {  // 拖拽结束发生该事件
      let tempPlayList = playList
      tempPlayList.splice(evt.newIndex, 0, playList.splice(evt.oldIndex, 1)[0]);
      // 更改播放列表顺序
      dispatch(changePlayListAction(tempPlayList))
    },
  });
}, [playList, dispatch]);
  1. Finish effect

Locally stored music list

Considering that immutable and redux-persise are not compatible with each other, the main reason is immutable the data format of redux-persist not known, which leads us to want redux cannot be stored locally. Try redux-persist-transform-immutable to convert the posture or use it incorrectly. The big guys who have used it, please give me some guidance. After doing it two or three times, I can only undo the code in the end. I am still too bad and crying 😥

Then another way of thinking, manually song list locally (only the song id is stored) , and save id in the song song list local Storage

Default song list

Every time we request a song, we actually only need to know the song id , so we only need to store the song id locally during the first initialization, but we need to store it locally. song id can be deduplicated (duplicate song id is not stored locally)

Achieve effect

Song order (asynchronous problem)

A small problem: when we traverse the song list array id send a network request, because the network request is sent asynchronously, the order of the songs in our music list is not in the order set by the sending array. Is there a way to How about sending this network request only after the last network request was successful?

The answer is yes, the first thought promise junior partner added chicken 🍗, of course, also be used async await

Ideas

(1)解决方案:promise + setinterval(定时器)
(2)可能有同学会问,为什么使用定时器呢?(不一定使用要使用定时器+promise这种方案)
(3)这是因为在咱们发送ajax时,不能很好的进行控制,使用一个标识变量来进行控制ajax是否发送(默认为true)
(4)在每次开始定时器时,首先判断标识变量是否为true如果为true就发送ajax,
  在本次请求ajax时设置标识变量为false(即在定时器中不会再发送网络请求),在本次ajax完成时(即异步操作成功时),改变标识变量为true
  这样就能进行很好的控制,简单的总结一下:就是必须控制本次ajax发送请求成功时,才能进行下一次ajax
  (核心在于使用标识变量,来控制ajax请求,且只有上次ajax请求成功,才能进行下一次ajax)

Code

export const getSongDetailArrayAction = (listId) => {
  return (dispatch, getState) => {
    // 1.获取歌曲列表
    const playList = getState().getIn(['player', 'playList'])
    let i = 0
    let timer = null
    let excuteRun = true // 控制ajax
    timer = setInterval(() => {
      let idx = listId[i]
      new Promise((resolve, reject) => {
        excuteRun &&
          getSongDetail(idx).then((res) => {
            excuteRun = false
            // console.log(res.songs[0])
            // (0)歌曲ID添加到本地存储
            addPlaylistId(idx)
            const song = res.songs && res.songs[0]
            // console.log(song)
            if (!song) return
            // (1)添加到播放列表中
            playList.push(song)
            dispatch(changePlayListAction(playList))
            // (2)更改当前播放的索引
            const songIndex = playList.length - 1
            dispatch(changeSongIndexAction(songIndex))
            // (3)更改当前播放歌曲
            dispatch(changeCurrentSongAction(song))
            // (4)请求歌曲的歌词
            dispatch(getLyricAction(idx))
            // (5)更新歌曲数量
            dispatch(changePlayListCount(playList.length))
            resolve(i)
          })
      }).then((value) => {
        excuteRun = true
      })
      i++
      if (i >= listId.length) {
        clearInterval(timer)
      }
    })
  }
}

effect

  • No matter how many times it is refreshed, it will be requested in the order id

To optimize

  • Support memorizing song list

    • After refreshing the page, the music playlist can remember the last play order
  • Remember the music played before closing the page

    • After refreshing the page, the currently playing song is memorized before closing the page, and the default song is the song played before closing when it is opened again

React to now, we have completed the basic functions of "NetEase Cloud Music PC". I believe you are already familiar with 060b89a1e0a928 Family Bucket. Next, where you want to expand, you can supplement and improve the functions yourself;

If there is any part of the article that you don’t understand or write badly, or have any suggestions, you are welcome to put forward it 🤗, I hope to make progress with everyone;

thank

  • Thank you very much Wang Hongyuan React core technology combat for letting me learn a lot of react knowledge.
  • Thank you very much to the background provider Binaryify , the interface is very stable, the documentation is perfect

风不识途
277 声望598 粉丝

学习前端


« 上一篇
React SSR