「ハンズオンシリーズ2」React戦闘デモ:ネットワークリクエストのカプセル化/検索の実装(アンチシェイク)/遅延読み込み/ useMemo()/reduxデータフロー管理/ホームページ

I.はじめに

このプロジェクトはreact新手入门、模倣コンポーネントのデモ用星巴克です。役立つ場合は、小さなものを提供してください点赞。次に、このプロジェクトは、オープンソースプロジェクトの神三元大物のコードを使用します: react-cloud-musicソースコードreact-cloud -説明する音楽小冊子使用したもののいくつかを説明します。react-cloud-music工具组件

1.0、ナンセンス

  • 主に、上司のプロジェクトを学ぶ方法について、いくつかの知識を自分のプロジェクト(理解)に統合したいと思います。网络请求プロジェクトの最初のエピソードから比較的大きな更新があります。他の元のページはreduxデータでのみ更新されますフロー管理。興味がある場合は、次のことができます收藏关注专栏

1.1。プロジェクトの表示とプロジェクトのアドレス

all.gif

  • スタイルの面では、仕事に追いつくためにうまくいっていませんrem适配。記事が公開された後、それは修改適応するために促進されます。
  • 可能であれば、サポートするスターを付けてください:プロジェクトのソースコードgithub
  • 可能であれば、それをサポートするために星を付けてください:プロジェクトソースコードgitee

1.2。このアップデートの内容

  • ネットワーク要求のカプセル化を行いますapi/config
  • 検索皿の画像安定化(debounce
  • メニューページの遅延読み込み(lazy-load
  • DFMを更新しますredux(なぜまだ使用しているのか聞かないでくださいredux
  • 検索中の人気のある検索のリスト(hotlist
  • ホームページカルーセルの実装(swiper

2. Redux

2.0、技術設計

  • このアップデートreduxは、新しいもの以外は変更されていません。
  • 相较于第一集,网络请求方面有较大的变化

2.1、理解redux(从useState过渡)

redux.jpg

reduxshow.gif

  1. 首先我不得不说,这个项目的数据量根本不至于用到redux,但是为了更好的理解redux,我还是把他加到了这个项目当中,那么我们要如何从原来在页面中通过useState()定义数据的初始状态,以及改变的setXXX()函数,到现在的redux数据流管理?
  2. 从页面的useState的思想中跳出来,当我们开发一个大型项目的时候,不可能把数据放在当前要运行的页面,这样不利于协同开发,页面多了数据也无法管理,所以我们用一个公共的数据仓库存一下页面所涉及的数据
  3. 当前页面要发生状态变化的时候,当前页面打一个电话给storestore收到了要变化的条件,返回给页面对应的状态,从而实现MVVM(具体实现中间还有很多过程,为了便于理解这么讲)。
  • Store:Store 就是保存数据的地方,你可以把它看成一个容器。
  • State:Store对象包含所有数据。如果在某个页面数据,就要对 Store 生成快照。
  • Action:在原来的useState中,State 的变化,会导致 View 的变化。但是,用户接触不到 State,只能接触到 View。所以,State 的变化必须是 View 导致的。Action 就是 View 发出的通知,表示 State 应该要发生变化了。
  • ActionCreators:指明Action变化的种类
  • dispatch():是 View 发出 Action 的唯一方法。
  • Reducer:Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

三、项目实现

3.0、封装网络请求

  • 上次我们把数据过滤放在数据请求里,这样请求一多,request文件会变得很复杂
  • 为了在代码上线时候可以快速修改localhost:3000服务器端url我们进行了一层封装,实现request.config
    {/*代码实现*/}
    // 配置请求对象
    import axios from 'axios'
    // 本地调试 dev 开发阶段,baseurl为远程基础url
    export const baseUrl = "https://www.fastmock.site/mock/5321bf649d06645c4266f3e0d45ae1cc";
    const axiosInstance = axios.create({
        baseURL: baseUrl
    })
    axiosInstance.interceptors.response.use(
        res => res.data,
        err => {
            console.log(err, '网络错误~~')
        }
    )
    export { axiosInstance }
    
    {/*代码实现*/}
    import axios from 'axios'
    import { axiosInstance } from "./config";
    export const getMenuListRequest =
        () => axiosInstance.get('/menu/all')
    export const getHotListRequest =
        () => axiosInstance.get('/menu/hot')
    

3.1、实现搜索+防抖+useMemo

debounce.gif

  • 这里把搜索懒加载放到0.8s实现搜索一次,效果明显一点,如果是自己写项目,0.3左右即可,太长用户体验不好
  • 搜索防抖的实现工具类随处可见,如果想自己实现的话可以参考下面的代码,甚至可以直接用lodash中的`debounce
  • 搜索实现
    1. 这里我仿造神三元大佬在其项目中的搜索,最外层用了一个Search组件,内层用SearchBox包了一层
    2. Search组件有一个query变量(便于理解我们叫他fatherQuery),和一个handleQuery函数用于修改fatherQuery
    3. SearchBox组件有自己的query(便于理解我们叫他sonQuery),同时接收传进来的Search中的fatherQueryhandleQuery
    4. SearchBox中修改的sonQuery,进行防抖处理,每隔800毫秒,执行一次handleQuery去修改Search中的fatherQuery ,因为最后是fatherQuery执行dispatch改变状态
    //父组件Search
    function Search(props) {
        const {hotList,suggestList} = props;
        const {getHotKeyMenuDispatch,getSuggestMenuDispatch} = props
        //这个useEffect只有每隔800ms才会得到重新渲染的机会
        useEffect(()=>{
            getSuggestMenuDispatch(query);
        },[query])
        //用于在子组件searchBox执行,更新父组件的query
        //但是子组件有防抖,需要每隔800ms执行一次
        const handleQuery = (q) =>{
            setQuery(q)
        }
        return( 
            <>
                <SearchBox newQuery={query} handleQuery={handleQuery}>
                </SearchBox>
            </>
        )
    }
    
    export default  memo(function SearchBox(props) {
    //得到父组件的变量与函数
    const {handleQuery} = props
    const [query,setQuery] = useState('')
    useEffect(() => {
        //父组件的query去dispatch更新状态
       handleQueryDebounce(query)
    }, [query])
    //防抖
    let handleQueryDebounce =  useMemo(() => {
       return debounce(handleQuery,800)
    }, [handleQuery])
    //返会给父组件query值
    const handleChange = (e) =>{
       let val = e.currentTarget.value
       setQuery(val)
    }
    return (
    <SearchWrapper>
        <div className="search_box">
          <input type="text" className='box' placeholder='搜索菜单' onChange={handleChange}  ref={queryRef}>
          </input>
          <i className='iconfont icon-sousuo' onChange={handleChange}></i>
        </div>
    </SearchWrapper>
       )
    })
    
  • useMemo
    1. 这里是一个很适合用到useMemo的地方,因为当fatherquery改变的时候会触发useEffect重新渲染整个子页面,但是我们handleQuery函数却不用每次都执行,useMemo()会记住这次运行的结果,是一个性能优化的好帮手,在跨页面数据流动减少复杂状态更新的地方常常用到。
    2. 例如网站首页加载了很多图片,但是我们跳到其他页面再回来又需要重新渲染这个页面,十分浪费性能,这种类似的情况就可以用到useMemo()
  • CSSTransition
    1. 这个是用来实现点击搜索后,页面从右到左划过的效果,需要的可以去仓库拉去样式

3.2、懒加载

lazyload.gif

  • 在菜单展示页面和搜索出来的菜品都有lazyload效果
  • lazyload的实现在今天已经非常简单了,以前可能还需要手写判断视口,或者用他人写好的工具库
  • 我们只需要npm i react-lazyload
  • img遍历的过程中加入Lazyload组件,并准备好替换图片放在placeholder
    {/*代码实现*/}
    <div className="good"> 
            {/* lazyload组件,用placeholder存放懒加载时的图片 */}
          <Lazyload placeholder={
            <img width="120%" height="100%"
                src={loading}
            />}>
              <img src={goodItem.img} alt=""/>
          </Lazyload>
          <div className="name">{goodItem.goods}</div>
    </div>
    

3.3、首页

HOME.gif

  • 首页差不多做到了1:1复刻,但是首页没有什么业务逻辑,所以后续估计也不会更新首页了,会着眼于其他页面的业务进行打造,争取做到一个比较适合前端面试的程度。
  • 轮播图的效果主要是运用了antdswiper组件
  • 如果首页有想了解的样式或者布局可以去仓库拉取。
    const swiper1_img = [img1,img2]
    //items遍历轮播图的图片
    const items = swiper1_img.map((item, index) => (
      <Swiper.Item key={index} >
        <img src={item} alt="" />
      </Swiper.Item>
    ))
    export default function Home() {
      return (
        <Container>
            <LoopImg>
              <div title='循环'>
                  {/*用items占位*/}
                <Swiper loop autoplay className='sw'>{items}</Swiper>
              </div>  
            </LoopImg>
        </Container>
     )}
    

第四に、終わり

最後に、私にとって非常に重要な1kbとgiteeに誰もがけちをつけないことを願っています。このプロジェクトをより完璧にするために、次のアップデートを楽しみにしています。そしておすすめアイテム、わかりにくい方はご購入いただけます、対応する取扱説明へのリンクがありますstar谢谢神三元大佬小册

ナゲッツテクノロジーコミュニティのクリエイター署名プログラムの募集に参加しています。リンクをクリックして登録し、送信してください。

おすすめ

転載: juejin.im/post/7120813140165525535