hooks 系列九:hooks 實戰

快來加入咱們吧!

"小和山的菜鳥們",爲前端開發者提供技術相關資訊以及系列基礎文章。爲更好的用戶體驗,請您移至咱們官網小和山的菜鳥們 ( xhs-rookies.com/ ) 進行學習,及時獲取最新文章。javascript

"Code tailor" ,若是您對咱們文章感興趣、或是想提一些建議,微信關注 「小和山的菜鳥們」 公衆號,與咱們取的聯繫,您也能夠在微信上觀看咱們的文章。每個建議或是贊同都是對咱們極大的鼓勵!css

實戰案例:留言功能

咱們學完了 react-hooks 的一些基礎內容,如今是咱們的一個實戰環節。html

項目的功能與咱們的 React 教程內容類似。具體可參考,React 系列 - 實戰案例:增長登陸前端

效果

咱們要作的實戰很簡單,就是一個簡單的留言功能。java

效果圖:react

DPIfpo6FKOvNB5g.gif

Login 頁面

登陸狀態維護

若是咱們登陸成功以後,咱們應該須要有一個用來存放信息的地方,爲以後進行鑑權作準備,咱們採用 localStorage 來作數據持久化處理。git

this.props.history.replace('/home')
window.localStorage.islogin = '1'
複製代碼

鑑權跳轉到首頁

咱們須要在登陸頁面鑑權,咱們讓 login 頁面在加載完成的時候判斷,若是已經登陸過了,那麼咱們就跳轉到 home 主頁,而要達到這樣的效果就須要在 useEffect() 中,在頁面展現以前進行判斷。github

useEffect(() => {
  let localStorage = window.localStorage
  if (localStorage.islogin === '1') {
    props.history.replace('/home')
  }
})
複製代碼

登陸頁所有代碼

用兩個 useState() 來記錄用戶輸入的帳號密碼,而後用於登陸驗證。web

import React, { useEffect, useState } from 'react'
import './login.css'

function Login(props) {
  useEffect(() => {
    let localStorage = window.localStorage
    if (localStorage.islogin === '1') {
      props.history.replace('/home')
    }
  })

  const [username, setUsername] = useState('')
  const [password, setPassword] = useState('')

  return (
    <div className="login"> <h2>歡迎來到XXX博客區</h2> <form className="form"> <div className="formItem"> <label htmlFor="username">用戶名:</label> <input type="text" id="username" value={username} onChange={(e) => setUsername(e.target.value)} /> </div> <div className="formItem"> <label htmlFor="password">密碼:</label> <input type="password" id="password" value={password} onChange={(e) => setPassword(e.target.value)} /> </div> <div className="loginBtn" onClick={() => handleLogin()}> 登陸 </div> </form> </div>
  )

  function handleLogin() {
    if (username && password) {
      props.history.replace('/home')
      window.localStorage.islogin = '1'
      alert('歡迎!')
    } else {
      alert('請輸入用戶名和密碼!')
    }
  }
}

export default Login
複製代碼

Home 頁面

import React, { useState } from 'react'
import Comment from './comment'
import checkRole from './checkRole'
import './App.css'

function App(props) {
  const [title, setTitle] = useState('Hello Hooks')
  const [desc, setDesc] = useState(
    '你知道有這麼一個團隊嗎?他們懷揣夢想,艱苦奮鬥,做爲一羣大學生菜鳥,放棄了平時娛樂的時間,選擇一塊兒學習,一塊兒成長,將平時學習的筆記,心得總結爲文章,目的很簡單,但願能夠幫助向他們同樣的菜鳥們?你想了解更多嗎?快搜索微信公衆號:小和山的菜鳥們,加入他們吧!',
  )
  const [comments, setComments] = useState([
    {
      headPortrait: 'https://xhs-rookies.com/img/rookie-icon.png',
      time: new Date(2021, 4, 14, 21, 2, 30),
      nickName: '小菜鳥',
      detail: '這是一個即將推出系列文章的團隊,咱們一塊兒期待他們的做品吧!',
      liked: true,
      likeNum: 23,
    },
  ])
  const [text, setText] = useState('')

  return (
    <div className="App"> <span className="logout" onClick={handleLogout}> 退出登陸 </span> <h2>{title}</h2> <div className="desc">{desc}</div> <div style={{ width: '100%' }}> <p className="commentsTitle">評論</p> {comments.map((item, index) => { return ( <Comment key={item.time.getTime()} changeLike={() => changeLike(index)} {...item} /> ) })} </div> <div className="newComment"> <div style={{ display: 'flex' }}> <img src="https://xhs-rookies.com/img/rookie-icon.png" className="" alt="" /> <textarea value={text} onChange={changeText} placeholder="請輸入評論" /> </div> <div className="submit" onClick={addComment}> 發表 </div> </div> </div>
  )
  // 退出登陸
  function handleLogout() {
    window.localStorage.islogin = '0'
    props.history.replace('/login')
  }
  // 改變text
  function changeText(e) {
    setText(e.target.value)
  }

  function changeLike(index) {
    let newArray = [...comments]
    let newItem = { ...newArray[index] }
    if (newItem.liked) {
      newItem.liked = false
      newItem.likeNum -= 1
    } else {
      newItem.liked = true
      newItem.likeNum += 1
    }
    newArray[index] = newItem
    setComments(newArray)
  }

  function addComment() {
    if (!text) {
      alert('請輸入留言內容')
      return
    }
    let detail = text
    setText('')
    let newComment = {
      headPortrait: 'https://xhs-rookies.com/img/rookie-icon.png',
      time: new Date(),
      nickName: '小菜鳥',
      detail,
      liked: false,
      likeNum: 0,
    }
    setComments([newComment, ...comments])
  }
}

export default App
複製代碼

用到的組件

comment 組件

這個組件是用來顯示用戶留言的,按數據展現。面試

import React from 'react'
import './comment.css'

function Comment(props) {
  const { nickName, time, headPortrait, detail, liked, likeNum, changeLike } = props
  return (
    <div className="comment"> <div className="info"> <img src={headPortrait} alt="頭像" /> <div> <p className="nickname">{nickName}</p> <p className="time">{getTime(time)}</p> </div> </div> <div className="detail" style={{ marginBottom: '10px' }}> {detail} </div> <div className="toolBox"> <span className={'likeBox ' + (liked ? 'like' : 'unlike')} onClick={changeLike}> <span className="icon"> </span> <span>{!!likeNum && likeNum}</span> </span> <span className="share icon"> </span> </div> </div>
  )

  function getTime(time) {
    const year = time.getFullYear()
    const month = time.getMonth() + 1
    const day = time.getDate()
    const hour = String(time.getHours()).padStart(2, '0')
    const minute = String(time.getMinutes()).padStart(2, '0')
    const second = String(time.getSeconds()).padStart(2, '0')
    return `${year}.${month}.${day} ${hour}:${minute}:${second}`
  }
}

export default Comment
複製代碼

總結

到這裏,咱們的 hooks 實戰就已經結束了,雖然只是一個簡單的留言功能,可是也包含了 hooks 的一些用法。

若是須要查看源碼的話,能夠查看並下載咱們的開源庫項目 github 地址

下節預告

hooks 的學習到此已經告一段落,接下來在這個金九銀十的時間段,咱們將爲你們帶來精彩的面試題目,敬請期待!

相關文章
相關標籤/搜索