Este é um aplicativo da web que imita o lado do PC do NetEase Cloud Music. Ele é construído com base no Vue + Element UI. O estilo geral da página é relativamente simples. a área de trabalho do Windows. O corpo principal do aplicativo é uma janela, que pode ser acessada arrastando o canto inferior direito para alterar o tamanho da janela. Embora possa ser um pouco estranho ser um aplicativo da Web projetado dessa forma, não é. inviável. Talvez um desktop web possa ser derivado no futuro, semelhante à sensação de um desktop em nuvem.
Parece ser uma boa ideia. Talvez no futuro você possa tentar construir um desktop web, fornecer uma plataforma básica para gerenciar o ciclo de vida de cada janela e, em seguida, desenvolver aplicativos web baseados nesta plataforma e colocar o seu próprio. aplicativos da web nele.
O back-end do projeto vem da API da versão NetEase Cloud Music NodeJS e do documento de interface completo do projeto
A página de documentação da interface deste projeto não está mais acessível. Gerei um documento offline, que você pode baixar aqui.
Ainda existem algumas páginas do projeto que não foram concluídas, mas as páginas principais foram concluídas, e o projeto será continuamente atualizado e implantado no meu NetEase Cloud Music (imitação)
Como o servidor é um servidor doméstico, e a resolução do nome de domínio para o host doméstico requer registro, e como não consigo passar no registro por não ter autorização de residência, só posso acessá-lo diretamente via IP.
Esta seção descreverá como fazer este projeto funcionar corretamente
$ git clone https://github.com/Binaryify/NeteaseCloudMusicApi.git
$ npm install
A porta padrão para inicialização do servidor é 3000. Se não quiser usar a porta 3000, você pode usar o seguinte comando: windows
$ set PORT=4000
Em Mac/Linux
$ PORT=4000
$ cd NeteaseCloudMusicApi
$ node app.js
$ git clone https://github.com/ColorlessWin/cloud_music.git
$ npm install
O endereço do servidor padrão do projeto é http://localhost
e a porta é 3000
Se você precisar modificá-lo, crie um novo arquivo .env.local
no diretório raiz deste projeto e anote os seguintes pares de valores-chave .
VUE_APP_HOST=/*这里填你的服务器地址(需要加http或https前缀)*/
VUE_APP_PORT=/*这里填你的服务器端口*/
/**
* 示例
* VUE_APP_HOST=https://webservices.fun
* VUE_APP_PORT=80
*/
$ npm run serve
$ npm run build
Este projeto contém um plug-in webpack auto-escrito. Sua função é carregar automaticamente os arquivos compilados para o servidor após
.env.local
conclusão da compilação. meu computador. Encontre o servidor e carregue o arquivo, para que ele relate um erro ao construir no seu computador, mas isso não afetará a construção do projeto.
Se você estiver executando apenas localmente, mantenha todas as configurações como padrão.
Esta parte apresentará <Rendering/>
, um componente central do projeto. Este componente é usado em um grande número de páginas do projeto. Compreender como esse componente funciona é uma maneira importante de entender a maior parte do código-fonte deste. projeto.
O componente
<Rendering/>
é responsável por renderizar todos os dados do projeto que podem ser abstraídos no formatoArray<Object>
. O projeto possui uma grande quantidade desses dados, como listas de músicas, listas de cantores, listas de álbuns, listas de comentários, etc. Dados em conformidade com o formatoArray<Object>
.E o componente
<Rendering/>
também assumirá o carregamento desses dados, processamento de paginação, etc. O que você precisa fazer é muito simples. Você só precisa implementar um métodofilling
e passá-lo para o componente<Rendering/>
através. adereços.
Apresentaremos este componente através de uma página simples no projeto.
Esta é uma página de classificação MV. Ao alternar diferentes tags de classificação, a página mostrará a lista MV correspondente. Há também uma função de paginação simples na parte inferior. Vamos ver como usar <Rendering/>
para implementar essas funções de maneira conveniente
Você pode tentar esta página primeiro
Paginação inferior
Vamos dar uma olhada na estrutura geral da parte do código-fonte desta página.
< template >
< span >地区:</ span >
< simple-radio :options = " areaLabel " v-model = " area " /> < br >
< span >类型:</ span >
< simple-radio :options = " typeLabel " v-model = " type " /> < br >
< span >排序:</ span >
< simple-radio :options = " orderLabel " v-model = " order " /> < br >
< rendering
class = " mvs "
:component = " require('@/components/content/matrices/CommonVideoMatrices').default "
:adapter = " adapter "
:show-creator = " true "
:total = " total "
:filling = " filling "
:unique = " area + type + order "
/>
</ template >
< script >
import ...
export default {
name : " Mv " ,
components : {LArea, Rendering, SimpleRadio},
data () {
return {
total : - 1 ,
area : '全部' ,
type : '全部' ,
order : '上升最快' ,
areaLabel : [ '全部' , '内地' , '港台' , '欧美' , '日本' ],
typeLabel : [ '全部' , '官方版' , '原声' , '现场版' , '网易出品' ],
orderLabel : [ '上升最快' , '最热' , '最新' ],
adapter : { ... }
}
},
methods : {
filling ( offset , limit , first_load ) { ... }
}
}
</ script >
Algum conteúdo que não requer atenção está dobrado aqui. Para o código-fonte completo, consulte aqui.
Você pode ver que a parte do modelo da página é relativamente simples. O primeiro são os três componentes <simple-radio/>
. Suas funções são muito simples. Os rótulos correspondentes são renderizados por meio dos três arrays Label definidos em data
. rótulos são clicados Em seguida, atualize as propriedades vinculadas correspondentes por meio de v-model
e, em seguida, um componente <rendering/>
com muitos adereços vinculados a ele.
<rendering/>
Detalhes do componente Parece que <rendering/>
tem muitos adereços, mas não é o caso <rendering/>
tem apenas 2 adereços, e outros adereços serão passados para seu <component/>
e <pagination/>
internos.
< template >
< div >
< component
:is = " component "
v-bind = " Object.assign(props, $attrs) "
v-on = " $listeners "
/>
< pagination
v-model = " props.datas "
v-on = " $listeners "
v-bind = " $attrs "
:filling = " filling "
/>
</ div >
</ template >
< script >
import Pagination from " @/components/common/Pagination " ;
export default {
name : " Rendering " ,
components : {Pagination},
props : {
component : { type : [ Object , Function ], required : true },
filling : { type : Function , required : true },
},
data () {
return {
props : {
datas : [],
}
}
}
}
</ script >
<Rendering/>
trecho de código-fonte, algum conteúdo que não precisa de atenção foi excluído aqui. Para o código-fonte completo, veja aqui.
<pagination/>
é um componente de paginação. É responsável por renderizar um componente de paginação para fornecer interação e também é responsável por gerenciar o carregamento de dados.
<component/>
é responsável por carregar os componentes que você passa por meio do component
prop. Nesta página MV, passo dinamicamente um componente CommonVideoMatrices
para component
por meio de require([path]).default
. component
e você pode ver que eu faço proxy dos eventos dentro de CommonVideoMatrices
por meio de v-on="$listeners"
, o que significa que você pode ouvir diretamente o evento $emit
dentro de CommonVideoMatrices
em <rendering/>
CommonVideoMatrices
é responsável por renderizar uma lista de exibição MV real. Na verdade, é responsável por exibir dados nesta página. Ele aceita internamente um suporte dedatas
(datas
devem sempre ser dados no formatoArray<Object>
) e os renderiza por meio da páginadatas
.Existem muitos componentes no projeto que são semelhantes ao design
CommonVideoMatrices
. Todos eles renderizam seus próprios dados por meio de uma propriedadedatas
src/cmoponents/content/tracks
Apenas um componente contendodatas
pode ser passado em<rendering/>
src/cmoponents/content/tracks
e emsrc/component/content/matrices
<Pagination/>
renderizará um componente de paginação na página para fornecer interaçãoEste componente de paginação só será renderizado quando você fornecer a propriedade
total
. Caso contrário, ele não será renderizado, mas você ainda poderá gerenciar o carregamento de dados. Para obter mais detalhes sobre<Pagination/>
você pode visualizar o código-fonte.
O texto acima apresenta a estrutura interna e alguns detalhes do componente <Rendering/>
<Rendering/>
menos sabemos que através component
, podemos passar um componente contendo datas
para ele. mas quem dará esse componente. datas
passa os dados, por meio de qual método?
Isso traz outro filling
de prop dentro do componente <Rendering/>
.
Ao contrário de outros adereços, filling
você precisa passar uma função para ele. Esta função será usada para carregar dados. Ela será chamada automaticamente quando necessário e será necessária para retornar uma promessa.
Podemos ver como esta função é implementada na página MV
methods: {
filling ( offset , limit , first_load ) {
return new Promise ( resolve => {
mvs ( this . area , this . type , this . order , offset , limit )
. then ( result => {
if ( first_load ) this . total = result [ 'count' ]
resolve ( result [ 'data' ] )
} )
} )
}
}
Esta função será passada como parâmetro para
<rendering/>
e seus internos serão passados para<pagination/>
e ele decidirá quando chamá-la.
mvs(area, type, order, offset, limit)
é uma interface para dados mv de backend. Os três primeiros parâmetros são usados para determinar que tipo de mv,offset
elimit
são usados para paginação.
Quando o componente de paginação renderizado na página por <pagination/>
é clicado, o método de preenchimento é chamado internamente e alguns parâmetros são passados. Esses parâmetros são usados como parâmetros de paginação pela interface mvs
e são passados por resolução quando os dados da interface são retornados. com sucesso. Para dentro de <pagination/>
, os dados serão armazenados em cache desta vez e serão passados para CommonVideoMatrices
por meio de <Rendering/>
para que os dados possam ser renderizados normalmente.
Filling também será chamado quando a página for carregada pela primeira vez.
Você pode ver que nossa página também precisa recarregar novos dados depois que o usuário seleciona outras tags ou categorias. Você pode pensar em ouvir o evento click de <simple-radio/>
e então notificar <pagination/>
de alguma forma. O método de preenchimento atualiza os dados?
Não precisa! ! Temos uma maneira mais simples de implementar esta função
< rendering
...
:unique =" area + type + order "
/>
unique
será eventualmente passado para<pagination/>
order
type
area
Eles estão todos vinculados a três<simple-radio/>
diferentes por meio dov-model
Eu só preciso adicionar uma propriedade unique
no componente <rendering/>
e passar para ele um valor que será usado para responder às atualizações de dados. Quando o valor passado para alterações unique
, o preenchimento será chamado. encontro Neste cenário, por exemplo, quando o id da playlist é alterado, os novos dados da playlist são recarregados. Neste momento, só precisamos passar o id para unique
e implementar um método de preenchimento. serão carregados automaticamente.
Você pode ver que <Rendering/>
é muito conveniente para usar nesta página. Ao escrever esta página, só podemos nos concentrar no conteúdo de CommonVideoMatrices
sem pensar no método e na lógica de aquisição de dados. carregando. Um efeito de animação de carregamento... será exibido. Eles também são concluídos por <Rendering/>
, mas esta parte foi simplificada no trecho de código mostrado aqui.
Na verdade, existe outra coisa chamada
adapter
que é usada para resolver o problema do backend retornar o mesmo tipo de dados em locais diferentes, mas com estruturas de dados diferentes, mas não vou apresentá-la aqui.
Este é um projeto para iniciantes. Espero que possa dar alguma inspiração e referência para alguns alunos que são novos no front-end/Vue e não conseguem encontrar nenhuma prática de projeto. Muitos lugares no projeto são implementados desta forma. que depois de ler esta parte, você possa ter uma compreensão mais clara de parte do código fonte deste projeto