從零開始搭建React開發專案之抖音“剪映”——創作課堂(基礎入門篇)

語言: CN / TW / HK

theme: mk-cute highlight: a11y-dark


持續創作,加速成長!這是我參與「掘金日新計劃 · 6 月更文挑戰」的第1天,點選檢視活動詳情

前言

React是近幾年來前端專案開發非常火的一個框架,其背景是Facebook團隊的技術支援,市場佔有率也很高,對於很多新手來說可能很多人都在猶豫是選react還是vue,如果時間充裕的話還是首選react(雖然有一點難),但不得不說React無論從效能上還是思想上(元件化)都比vue更為先進。下面我帶來的react元件化設計希望能夠幫助到一些和我一樣剛學習react的新手

元件展示

  • 剪映原版

QQ圖片20220625112326.jpg - 仿剪映盜版

1s.gif

2s (1).gif

專案搭建與安裝依賴

  1. 專案初始化 npm init @vitejs/app 選擇react (這裡我使用的是vite搭建專案,如果大家用其他的更順手也可以用其他的)
  2. 安裝相關依賴 npm react-router react-router-dom
  3. 其他相關依賴
    • npm i axios 使用ajax請求服務端介面(這裡我使用的是fastmock https://www.fastmock.site/#/  線上模擬ajax請求)
    • npm i classnames 用來合併類名的,存在多個類名變數時,想新增到對應的元素中
    • npm i styled-components 使用atyled-components設定頁面樣式
    • npm i swiper 使用swiper輪播圖 注意下載的版本是4.5.0的(這裡我先前安裝的是最新版本的不會用導致輪播圖輪播根本動不了)
  4. 建立資料夾
    • 根目錄 public 靜態資源目錄 不需要在src 裡面引入
    • src下
      • api 封裝axios介面
      • assets 放置靜態資源 如圖片/字型圖示/全域性樣式
      • components 放置通用元件
      • pages 單頁面存放
      • routers 獨立配置檔案 把元件封裝到一起

1.png

  1. 啟動專案 npm run dev 預設在3000埠
  2. 初始化設定
    • 不同型號手機端適應頁面
    • 在public資料夾下建立js子資料夾建立adapter.js檔案

      這裡設定20px為1rem 後面所有的大小將不再使用px,使用rem代替px確保能夠適應所有的手機型號 ```js var init = function () { var clientWidth = document.documentElement.clientWidth || document.body.clientWidth; if (clientWidth >= 640) { clientWidth = 640; } var fontSize = 20 / 375 * clientWidth; document.documentElement.style.fontSize = fontSize + "px"; }

      init();

      window.addEventListener("resize", init); - 下載相應的圖示、圖片和對樣式reset - 在assets 下建立font、image和styles資料夾 - 字型圖示就在iconfont上去下載自己想要的或者使用font-awesome元件庫 - image 可以下載需要的圖示或者等會在fastmock傳入資料(可要可不要) - reset 就是對頁面進行樣式重置(這裡程式碼太長,推薦隨便到掘金或者github上找一個比較全的樣式重置就好了) - 匯入資料 - api資料夾下建立request.js檔案 封裝axios 首先在fastmock上建立好資料(這裡是我的fastmock地址)js import axios from 'axios'

      export const getCourse=()=> axios.get('https://www.fastmock.site/mock/758a51ea7ac094acd3f3de097e2da039/beers/course')

      ```

image.png

頁面設計思路

  • 頁面級別元件 <Home/> 他是其他頁面的父元件
    • <Header/> 頭部元件每個頁面都需要使用
    • <Footer/> 尾部元件tabbar 可以切換頁面
    • <HomeDetailNav/> 由這個元件切換到二級頁面
  • 精品課二級頁面
    • <Banner/> 錄播圖元件
    • <Lists /> 列表展示元件
    • <Course/> 課程展示頁面

image.png

專案頁面詳細設計

路由配置

這個專案的路由配置有點多,會用到二級路由,所以我們將所有的路由單獨封裝到routers資料夾下 這裡使用lazy懶載入,提升主頁開啟的速度

我主要寫的是Home和Jingpin元件,其他頁面主要是佔位,在後續會完成其他頁面的製作 ```jsx import { useState, lazy } from 'react' import { Routes, Route, Link} from 'react-router-dom' import Home from '../pages/Home' const Course = lazy(() => import('../pages/Course')) const Jianji = lazy(() => import('../pages/JianJi')) const Mine = lazy(() => import('../pages/Mine')) const News = lazy(() => import('../pages/News')) const TongKuan = lazy(() => import('../pages/Tongkuan')) const Jianpai = lazy(() => import('../pages/Jianpai')) const Mianfei = lazy(() => import('../pages/Mianfei')) const Tuijian = lazy(() => import('../pages/Tuijian')) const Zhibo = lazy(() => import('../pages/Zhibo')) const Jingpin = lazy(() => import('../pages/Jingpin'))

// Routes 不能和react-router-dom 一樣 const RoutesConfig = () => {

return (
    <Routes>
        <Route path='/' element={<Home/>}>
            <Route path='/' element={<Jingpin/>}/>
        </Route>
        <Route path='/jianji' element={<Jianji/>}></Route>
        <Route path='/tongkuan' element={<TongKuan/>}></Route>
        <Route path='/home' element={<Home/>}>
            {/* 二級路由 */}
            <Route path='/home/tuijian' element={<Tuijian/>}/>
            <Route path='/home/mianfei' element={<Mianfei/>}/>
            <Route path='/home/jingpin' element={<Jingpin/>}/>
            <Route path='/home/' element={<Jingpin/>}/>
            <Route path='/home/zhibo' element={<Zhibo/>}></Route>
            <Route path='/home/jianpai' element={<Jianpai/>}/>
        </Route>
        <Route path='/news' element={<News/>}></Route>
        <Route path='/mine' element={<Mine/>}></Route>
        <Route path='/course/:id' element={<Course/>}></Route>
    </Routes>
)

}

export default RoutesConfig ```

App.jsx

在App.jsx中程式碼很簡單,由Header元件和Footer元件 還有頁面二級路由元件構成

這裡使用Suspense 等待非同步元件時渲染一些額外內容,讓應用有更好的使用者體驗,在頁面還沒有加載出來時提示loading載入中 ``` jsx import { useState,Suspense } from 'react' import './App.css' import RoutesConfig from './routers' import Header from './components/Header' import Footer from './components/Footer'

function App() {

return (

loading...\
}>
) }

export default App ```

Header元件展示

  • 頭部做的是一個輸入框和一個div盒子放置,引入了字型圖示iconfont,這裡只是簡單的切頁面,具體樣式就不展示了

image.png

jsx <Header> <div className="inphead"> <i className='iconfont icon-sousuo sousuo'></i> <input type="text" placeholder='好友組團卡點照' className='inp' /> <div className='stu'> <i className='iconfont icon-24gl-playSquare'></i> <p>學習中心</p> </div> </div> </Header> ### Footer元件展示 - 這裡使用路由NavLink實現對頁面的跳轉 當跳轉到當前底部圖示和文字時會高亮顯示 jsx export default function Footer() { const {pathname}=useLocation() return ( <FooterWrapper> <NavLink to="/jianji" className={classnames({active:pathname=='/jianji'})}> <i className='iconfont icon-jianji'></i> <span>剪輯</span> </NavLink> <NavLink to="/tongkuan" className={classnames({active:pathname=='/tongkuan'})}> <i className='iconfont icon-shipin'></i> <span>剪同款</span> </NavLink> <NavLink to="/home" className={classnames({active:pathname=='/home' || pathname=='/'})}> <i className='iconfont icon-wodekecheng'></i> <span>創作課堂</span> </NavLink> <NavLink to="/news" className={classnames({active:pathname=='/news'})}> <i className='iconfont icon-xiaoxi'></i> <span>訊息</span> </NavLink> <NavLink to="/mine" className={classnames({active:pathname=='/mine'})}> <i className='iconfont icon-31wode'></i> <span>我的</span> </NavLink> </FooterWrapper> ) }

image.png

二級路由

<Home/>元件中引入<HomeDetailNav/>二級元件和使用<Outlet />對下面的元件進行佔位 下面主要介紹<HomeDetailNav/>元件

``jsx export default function HomeDetailNav(){ let homeNavs = [ { id: 1, desc: '推薦', path: '/tuijian'}, { id: 2, desc: '免費專區', path: '/mianfei'}, { id: 3, desc: '精品課', path: '/jingpin'}, { id: 4, desc: '直播', path: '/zhibo'}, { id: 5, desc: '拍剪教學', path: '/jianpai'}, ] return( <Wrapper > <div className="navbar swiper-container"> <div className="nav-box swiper-wrapper"> { homeNavs.map((item, index) => { return ( <NavLink index={index} to={/home${item.path}`} key={item.id} className="nav-item swiper-slide" > {item.desc} ) }) } ) }

``` 這裡使用map迴圈輸出二級路由的地址 點選不同的文字可以到不同的頁面 且路由有高亮顯示

router.gif

精品課頁面元件介紹

輪播圖設計

<Banner/>元件這裡使用swiper元件庫對輪播圖進行設定 使用useEffect鉤子對輪播圖進行渲染,輪播圖設定3秒自動輪播

```jsx export default function Banner() { useEffect(() => { new Swiper('.home_info_banner',{ loop:true, autoplay: { delay:3000 } }) },[]) return (

                <img src={img1} alt="" width="100%" />

        </div>
        <div className="swiper-slide">

                <img src={img2} alt="" width="100%" />

        </div>
    </div>
    <div className="swiper-pagination"></div>
  </div>
  </div>
</Wrapper>

) } ```

swiper.gif

列表展示

<Lists/> 這個元件很簡單就是使用一級路由直接跳轉

jsx <Link to="/kecheng"> <i className='iconfont icon-wodekecheng'></i> <span>全部課程</span> </Link> ...

課程元件

<Course/> 課程元件 負責課程的展示 這裡由fastmock傳入資料

佈局使用彈性佈局加absolute定位 jsx <Wrapper> {/* <h1>超值限時搶</h1> */} { course&&course.map( item=>( <div className="course-flex"> <Link className='course-List' to={`/course/${item.id}`} key={item.id} > <div className="course-Box"> <div className="course-Img"> <img src={item.img} alt="" /> <div className="get-Course"> <p>{item.coursenum}節課</p> </div> </div> <div className="course-Content"> <div className="course_header">{item.header}</div> <div className="course_name"> <span>{item.name}</span> <p>|</p> <span>{item.people}</span> </div> <div className="course_price"> <span className='course_price_now'><p>¥</p>{item.price}</span> <span className='course_price_old'><p>¥</p>{item.low_price}</span> </div> </div> </div> </Link> </div> ) ) } </Wrapper> 這裡我沒找到合適的圖片就都用了相同的圖片,後續如果找到了會修改的

image.png

最後

專案待改進地方

這個元件我做的比較簡單,就是簡單的切頁面和路由轉換,還有很多地方還沒有做出來,後續會繼續更新,完成這個專案,請持續關注

後續專案待完善地方

  1. 完善換一換,可以切換到下一頁
  2. 點進課程可以看到課程內容
  3. 再寫幾個頁面

專案地址

https://gitee.com/boluotou12/react-jianying/tree/master

感謝看到最後,如果覺得文章還不錯的話點個贊再走吧 (^▽^)