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
- Online preview address👉: Click I jump to Cloud Music
Project
Gihub
address👉: Musci 163 (If you think the project is not bad👏, give a star ⭐ Encourage it~)
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
Homepage
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
- Page layout construction
- Click the button to show and hide (playlist) and add transition effects
- It is mutually exclusive with the lyrics display control. (Lyrics list display, turn off lyrics display)
- Conten content build
Click on an item to play the corresponding music, and the background is highlighted
- After clicking the current item, will
id
transfer function, according toid
distributedaction
, 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 toredux
currentSongIndex
)
- Corresponding to
- After clicking the current item, will
- Click the delete button to prevent the event from bubbling and clear the click-to-play song
- Click the clear all button to clear all music and play the next music
2. Lyrics highlighting effect
Lyrics interface
Request interface:
Parse the requested lyrics
- In the previous section, we have stored it in
redux
, please refer to Lyric format
- In the previous section, we have stored it in
- Realize the highlight display of the lyrics currently being played, and get whether the current playing status is scrolling the lyrics
3. Lyrics scrolling effect
- According to the
index
currently playing lyrics, the scrolling effect is realized - Get
DOM
, calculatescrollTop
, 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
- installation
npm install sortablejs --save
yarn add sortablejs
- Import
import Sortable from 'sortablejs';
- 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]);
- Finish effect
Locally stored music list
Considering that
immutable
andredux-persise
are not compatible with each other, the main reason isimmutable
the data format ofredux-persist
not known, which leads us to wantredux
cannot be stored locally. Tryredux-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 listlocal 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 usedasync 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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。