React实现(Web端)网易云音乐项目(一),错过了真的可惜呀

首先肯定是搭建项目的结构了,通过脚手架安装这部分我就不说了

首先看项目的目录结构

React实现(Web端)网易云音乐项目(一),错过了真的可惜呀_第1张图片

assets:放我们的静态资源,图片,字体和公共初始样式等
common:放我们公共的JS文件
components:放我们项目的公共组件
pages:放项目的主视图组件
router:放项目的路由配置
services:网络请求部分
store:放redux的相关配置
utils:放一些处理我们数据的JS方法

一.我们引入文件的时候经常就是这样

  ../../../../

感觉太邋遢了
安装一个插件吧

yarn add @craco/craco

然后在我们项目的根目录,也就是src的同级目录,建立一个craco.config.js

// 导入文件可以用@
const path = require("path");

const resolve = dir => path.resolve(__dirname, dir);

module.exports = {
  webpack: {
    alias: {
      "@": resolve("src"),
      "components": resolve("src/components")
    }
  }
}

然后在我们的package.json中,将scripts改成这样的
React实现(Web端)网易云音乐项目(一),错过了真的可惜呀_第2张图片

今后导入我们的任何文件直接这样写

import {  } from '@/common';
import  from '@/components';

二.先定义一些初始样式比较好,在入口index.js引入,项目主要是用styled-components写的

yarn add normalize.css

然后在assets中建立一个css文件,css文件里面建立一个reset.css

@import "~normalize.css";

/* 样式的重置 */
body, html, h1, h2, h3, h4, h5, h6, ul, ol, li, dl, dt, dd, header, menu, section, p, input, td, th, ins {
  padding: 0;
  margin: 0;
}

ul, ol, li {
  list-style: none;
}

a {
  text-decoration: none;
  color: #666;
}

a:hover {
  color: #666;
  text-decoration: underline;
}

i, em {
  font-style: normal;
}

input, textarea, button, select, a {
  outline: none;
  border: none;
}

table {
  border-collapse: collapse;
  border-spacing: 0;
}

img {
  border: none;
  vertical-align: middle;
}

/* 全局样式 */
body, textarea, select, input, button {
  font-size: 12px;
  color: #333;
  font-family: Arial, Helvetica, sans-serif;
  background-color: #f5f5f5;
}

.text-nowrap {
  white-space: nowrap;
  text-overflow: ellipsis;
  overflow: hidden;
}

.wrap-v1 {
  width: 1100px;
  margin: 0 auto;
}

.wrap-v2 {
  width: 980px;
  margin: 0 auto;
}

.sprite_01 {
  background: url(../img/sprite_01.png) no-repeat 0 9999px;
}

.sprite_02 {
  background: url(../img/sprite_02.png) no-repeat 0 9999px;
}

.sprite_covor {
  background: url(../img/sprite_cover.png) no-repeat 0 9999px;
}

.sprite_icon {
  background: url(../img/sprite_icon.png) no-repeat 0 9999px;
}

.sprite_icon2 {
  background: url(../img/sprite_icon2.png) no-repeat 0 9999px;
}

.sprite_button {
  background: url(../img/sprite_button.png) no-repeat 0 9999px;
}

.sprite_button2 {
  background: url(../img/sprite_button2.png) no-repeat 0 9999px;
}

.sprite_table {
  background: url(../img/sprite_table.png) no-repeat 0 9999px;
}

.image_cover {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  text-indent: -9999px;
  background: url(../img/sprite_cover.png) no-repeat -145px -57px;
}

我先把这些样式写这了,因为网易云音乐,它里面很多的图片都用的是精灵图,我提前给他们把位置和样式确定了一下

这篇博客就先完成下面这个,我们先把基本的框架和路由搭好
在这里插入图片描述

三.先在pages里面建立三个视图文件,discover,friend,mine(其他几个是跳转外部链接的,不需要路由)

import React, { memo } from 'react';

export default memo(function LSHDiscover() {
  return (
    

LSHDiscover

) }) import React, { memo } from 'react'; export default memo(function LSHFriend() { return (

HYFriend

) }) import React, { memo } from 'react'; export default memo(function LSHMine() { return (

LSHMine

) })

然后discover有6个子路由,我就不一一写了

React实现(Web端)网易云音乐项目(一),错过了真的可惜呀_第3张图片

至于为什么用memo?节省性能

组件仅在它的 props 发生改变的时候进行重新渲染

四.配置路由

yarn add react-router-config
yarn add react-router-dom

在我们的router文件中建立一个index.js

import React from 'react'

import LSHDiscover from "@/pages/discover";
import HYRecommend from "@/pages/discover/c-pages/recommend";
import HYRanking from "@/pages/discover/c-pages/ranking";
import HYSongs from "@/pages/discover/c-pages/songs";
import HYDjradio from "@/pages/discover/c-pages/djradio";
import HYArtist from "@/pages/discover/c-pages/artist";
import HYAlbum from "@/pages/discover/c-pages/album";

import LSHMine from "@/pages/mine";
import LSHFriend from "@/pages/friend";

import {Redirect} from 'react-router-dom'    
Redirect是为了重定向,当进页面的时候展示哪一个

下面是routes

const routes = [
  {
    path: "/",
    exact:true,
    render:()=>(
      
    )
  },
  {
    path: "/discover",
    component: LSHDiscover,
    routes: [
      {
        path: "/discover",
        exact: true,
        render: () => (
          
        )
      },
      {
        path: "/discover/recommend",
        component: HYRecommend
      },
      {
        path: "/discover/ranking",
        component: HYRanking
      },
      {
        path: "/discover/songs",
        component: HYSongs
      },
      {
        path: "/discover/djradio",
        exact: true,
        component: HYDjradio
      },
      {
        path: "/discover/artist",
        component: HYArtist
      },
      {
        path: "/discover/album",
        component: HYAlbum
      }
    ]
  },
  {
    path: "/mine",
    component: LSHMine
  },
  {
    path: "/friend",
    component: LSHFriend
  },
];

同时别忘了导出

export default routes

五.在APP.js中配置

import React, { memo } from 'react'
import {renderRoutes} from 'react-router-config'
import { HashRouter } from 'react-router-dom';
import routes from './router'

import LSHAppHeader from '@/components/app-header'

export default memo(function App() {
  return (
    
      
      {renderRoutes(routes)}
    
  )
})

在这里我们用的是hash路由,LSHAppHeader是我们下面这个,下面开始写
在这里插入图片描述
六.开始app-header组件的编写

在components中创建一个app-header文件,里面建立一个index.js和style.js

由于我们这个东西用到了antd这个ui库,先安装一下,别忘了导入样式,可以在我们定义的reset.css中导入

@import "~antd/dist/antd.css";

安装antd

yarn add antd
yarn add @ant-design/icons

index.js

import React, { memo } from 'react';

import { headerLinks } from '@/common/local-data'

import { NavLink } from 'react-router-dom';
import { SearchOutlined } from '@ant-design/icons'
import { Input } from 'antd'
import {
  HeaderWrapper,
  HeaderLeft,
  HeaderRight
} from './style'

export default memo(function LSHAppHeader() {
  //业务代码
  const showSelectItem = (item, index) => {
    if (index < 3) {
      return (
        
          {item.title}
          
        
      )
    } else {
      return {item.title}
    }
  }

  //返回到jsx
  return (
    
      
网易云音乐
{ headerLinks.map((item, index) => { return (
{showSelectItem(item, index)}
) }) }
} />
创作者中心
登录
) })

headerLinks是我们一些公共js数据,在common中创建一个local-data.js

export const headerLinks = [
  {
    title: "发现音乐",
    link: "/discover"
  },
  {
    title: "我的音乐",
    link: "/mine"
  },
  {
    title: "朋友",
    link: "/friend"
  },
  {
    title: "商城",
    link: "https://music.163.com/store/product"
  },
  {
    title: "音乐人",
    link: "https://music.163.com/nmusician/web/index#/"
  },
  {
    title: "下载客户端",
    link: "https://music.163.com/#/download"
  }
]

style.js样式为,要先安装我们的styled-components,yarn add styled-components

import styled from "styled-components";

export const HeaderWrapper = styled.div`
  height: 75px;
  font-size: 14px;
  color: #fff;
  background-color: #242424;

  .content {
    height: 70px;

    display: flex;
    justify-content: space-between;
  }

  .divider {
    height: 5px;
    background-color: #C20C0C;
  }
`

export const HeaderLeft = styled.div`
  display: flex;

  .logo {
    display: block;
    width: 176px;
    height: 69px;
    background-position: 0 0;
    text-indent: -9999px;
  }

  .select-list {
    display: flex;
    line-height: 70px;
    
    .select-item {
      position: relative;
      a {
        display: block;
        padding: 0 20px;
        color: #ccc;
      }

      :last-of-type a {
        position: relative;
        ::after {
          position: absolute;
          content: "";
          width: 28px;
          height: 19px;
          background-image: url(${require("@/assets/img/sprite_01.png")});
          background-position: -190px 0;
          top: 20px;
          right: -15px;
        }
      }

      &:hover a, a.active {
        color: #fff;
        background: #000;
        text-decoration: none;
      }
      
      .active .icon {
        position: absolute;
        display: inline-block;
        width: 12px;
        height: 7px;
        bottom: -1px;
        left: 50%;
        transform: translate(-50%, 0);
        background-position: -226px 0;
      }
    }
  }
`

export const HeaderRight = styled.div`
  display: flex;
  align-items: center;
  color: #ccc;
  font-size: 12px;


  .search {
    width: 158px;
    height: 32px;
    border-radius: 16px;

    input {
      &::placeholder {
        font-size: 12px;
      }
    }
  }

  .center {
    width: 90px;
    height: 32px;
    line-height: 32px;
    text-align: center;
    border: 1px solid #666;
    border-radius: 16px;
    margin: 0 16px;
    background-color: transparent;
  }
`

好了,最顶部的完成了

下面写这个discover的子路由视图
在这里插入图片描述
我们去到discover这个文件的index.js中

import React, { memo } from 'react';
//子路由渲染
import { renderRoutes } from 'react-router-config';

import { dicoverMenu } from "@/common/local-data";

import { NavLink } from 'react-router-dom';

import {
  DiscoverWrapper,
  TopMenu
} from './style';

export default memo(function LSHDiscover(props) {
  // 子路由渲染
  const { route } = props;

  return (
    
       
{ dicoverMenu.map((item, index) => { return (
{item.title}
) }) }
{renderRoutes(route.routes)}
) })

dicoverMenu这个文件的东西

export const dicoverMenu = [
  {
    title: "推荐",
    link: "/discover/recommend"
  },
  {
    title: "排行榜",
    link: "/discover/ranking"
  },
  {
    title: "歌单",
    link: "/discover/songs"
  },
  {
    title: "主播电台",
    link: "/discover/djradio"
  },
  {
    title: "歌手",
    link: "/discover/artist"
  },
  {
    title: "新碟上架",
    link: "/discover/album"
  },
]

style.js

import styled from 'styled-components';

export const DiscoverWrapper = styled.div`
  .top {
    height: 30px;
    background-color: #C20C0C;
  }
`

export const TopMenu = styled.div`
  display: flex;
  padding-left: 180px;
  position: relative;
  top: -4px;

  .item {
    a {
      display: inline-block;
      height: 20px;
      line-height: 20px;
      padding: 0 13px;
      margin: 7px 17px 0;
      color: #fff;

      &:hover, &.active {
        text-decoration: none;
        background-color: #9B0909;
        border-radius: 20px;
      }
    }
  }
`

好了,这个页面基本就完成了,下一篇博客就要通过网络请求获取数据到我们redux中存储了,这两个页面

React实现(Web端)网易云音乐项目(一),错过了真的可惜呀_第4张图片
github项目地址:https://github.com/lsh555/WY-Music

你可能感兴趣的:(react,网易云音乐,js)