<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          React + TypeScript + Taro前端開(kāi)發(fā)小結(jié)

          共 5929字,需瀏覽 12分鐘

           ·

          2022-04-17 01:56

          前言

          項(xiàng)目到一段落,先來(lái)記錄一下,本文以前端新手的角度記錄React、TypeScript、Taro相關(guān)技術(shù)的開(kāi)發(fā)體驗(yàn)以及遇到的問(wèn)題和解決方法。

          之前總說(shuō)要學(xué)React(這篇博客:代碼使我頭疼之React初學(xué)習(xí)),這次項(xiàng)目需要做H5前端+小程序,我終于能用上React了~

          使用React的開(kāi)發(fā)框架之前就聽(tīng)過(guò)京東的Taro,所以就這個(gè)了,直接開(kāi)碼。

          關(guān)于React

          不錯(cuò),感覺(jué)比Vue的模板寫法自由很多,我看Taro文檔的例子都是class組件,但一開(kāi)始「前端帶師」就推薦我用function組件,現(xiàn)在我全都是用function組件,react就該這么寫,真香~

          因?yàn)橹皩懥艘欢螘r(shí)間的Flutter,所以react對(duì)我來(lái)說(shuō)很親切,至少可以無(wú)縫上手聲明式UI的寫法。

          不過(guò)我感覺(jué)React的生態(tài)太大,更新太快了,有點(diǎn)碎片化,很多第三方庫(kù)官方文檔都跟不上更新速度(批評(píng)一下mobx,害人不淺)

          話說(shuō)一開(kāi)始我看了某位知乎大V的那本React和Redux的書,應(yīng)該是我太菜的原因,感覺(jué)不是很容易理解,果然技術(shù)厲害的大佬不一定教書也厲害嗎~

          參考資料

          • React 入門 - 從js的角度理解 react:https://github.com/coppyC/blog/issues/16

          關(guān)于TypeScript

          第一次用TypeScript,不過(guò)作為日常用C#寫后端的人,又處處是熟悉的感覺(jué)~

          反正比JS好用一萬(wàn)倍就是了,類型提示真是太棒了

          目前用得不深,后續(xù)有什么相關(guān)的我再寫寫博客記錄一下。

          參考資料

          • 探索 TypeScript 類型注解 - 自定義類型:https://github.com/WowBar/blog/issues/9

          Taro框架使用感受

          框架是個(gè)好框架,不過(guò)文檔方面感覺(jué)還不是很完善,有些地方寫得不是很清楚,感覺(jué)很多文檔都是復(fù)制了微信小程序的文檔來(lái)的,對(duì)于沒(méi)開(kāi)發(fā)過(guò)微信小程序且沒(méi)讀過(guò)微信官方文檔的人來(lái)說(shuō),不是很友好。(不過(guò)官方文檔還是要看,不看的話遇到很多問(wèn)題都查不到的)

          然后Taro官方提供了一個(gè)UI庫(kù),叫 TaroUI,用的話還是能用的,就是更新太慢了,它的github項(xiàng)目主頁(yè) 顯示上次更新時(shí)間還是去年(2021年)6月份,到現(xiàn)在近一年時(shí)間沒(méi)動(dòng)過(guò)了。最新穩(wěn)定版本還在2.x,而Taro框架已經(jīng)更新到3版本了。

          因?yàn)槲矣玫腡aro框架是3.x版本,所以只能硬著頭皮上TaroUI 3的beta版本,導(dǎo)致遇到了一些奇奇怪怪的問(wèn)題,頭大。

          除了TaroUI這個(gè)界面庫(kù),Taro官方還提供另一個(gè)叫 NutUI 的庫(kù),不過(guò)是基于Vue的,我這個(gè)項(xiàng)目沒(méi)法用,這個(gè)庫(kù)就更新挺勤快的,github上最近更新還是6小時(shí)前,Star也有4.2k,比TaroUI的3.9k多。(看來(lái)React在京東不受待見(jiàn)呀~)

          我還看到有一個(gè)叫 Taroify 的UI庫(kù),看起來(lái)好像不錯(cuò),更新也很勤快,不過(guò)GitHub Stars只有300多,不敢用~ 下次來(lái)試試看

          用的同時(shí)我還參考了這些項(xiàng)目/代碼/文檔:

          • https://github.com/NervJS/taro-v2ex/blob/react/src/pages/thread_detail/thread_detail.tsx
          • https://github.com/wuba/Taro-Mortgage-Calculator
          • https://github.com/NervJS/awesome-taro

          接下來(lái)進(jìn)入正題,總體說(shuō)說(shuō)遇到的一些問(wèn)題/坑,以及解決方案。

          頁(yè)面路由問(wèn)題

          Taro封裝了路由相關(guān)的方法,我是做完了項(xiàng)目有時(shí)間去翻一下 微信小程序文檔 才發(fā)現(xiàn)這玩意跟小程序的路由特別像。

          PS:我討厭這種路由設(shè)計(jì),不知道小程序這樣是哪個(gè)人才想出來(lái)的,頁(yè)面多了的話不太好維護(hù)啊~

          app.config.ts 文件里把路由配置好,類似這樣:

          export?default?defineAppConfig({
          ??pages:?[
          ????'pages/index/index',
          ????'pages/info/place',
          ????'pages/supply/index',
          ????'pages/user/login',
          ??],
          ??window:?{
          ????backgroundTextStyle:?'light',
          ????navigationBarBackgroundColor:?'#fff',
          ????navigationBarTitleText:?'WeChat',
          ????navigationBarTextStyle:?'black'
          ??},
          })

          然后要跳轉(zhuǎn)的地方就用 Taro.navigateTo({url: 'pages/user/login'}) 就行了

          這里有個(gè)很坑的地方!Taro的熱更新不完善,添加了新頁(yè)面后熱更新是不生效的,必須 yarn dev:h5 重啟才能看到效果,一開(kāi)始我被坑得嗷嗷叫~

          地址參數(shù)問(wèn)題

          這個(gè)問(wèn)題在我之前的博客:Django + Taro 前后端分離項(xiàng)目實(shí)現(xiàn)企業(yè)微信登錄 有提到,Taro本身提供了 useRouter() 來(lái)給我們讀取地址里的參數(shù)

          比如上面那個(gè)路由跳轉(zhuǎn)的地方我們加上了參數(shù):Taro.navigateTo({url: 'pages/user/login?title=hello'})

          那我們?cè)?pages/user/login 頁(yè)面里要獲取參數(shù)就是這樣

          import?{useEffect}?from?"react"
          import?{useRouter}?from?"@tarojs/taro"

          export?default?function?()?{
          ????const?router?=?useRouter()
          ????
          ????useEffect(()?=>?{
          ????????console.log(router.params.title)
          ????},?[])
          }

          但當(dāng)在讀取微信登錄服務(wù)器回調(diào)參數(shù)的時(shí)候,就不行,就取不出來(lái),得自己拿完整鏈接 window.location.href 去匹配。詳見(jiàn)我這篇博客:Django + Taro 前后端分離項(xiàng)目實(shí)現(xiàn)企業(yè)微信登錄

          Taro.relaunch不會(huì)清除URL

          這看起來(lái)不是什么大問(wèn)題,不過(guò)也導(dǎo)致了一個(gè)小bug,就是我在使用微信登錄后,注銷登錄的時(shí)候不會(huì)清除地址里的code,這樣沒(méi)關(guān)閉頁(yè)面的情況下,再次使用微信登錄,那個(gè)code還是舊的,就直接報(bào)錯(cuò)了~

          TaroUI form的bug

          說(shuō)實(shí)話我不知道這是哪里的問(wèn)題

          只有一個(gè)頁(yè)面出現(xiàn)了這個(gè)問(wèn)題,在最后一個(gè)輸入框按回車,表現(xiàn)是form提交,但其實(shí)也沒(méi)提交,并且頁(yè)面變成重新刷新了

          百思不得其解

          我只好在最后面再加了一個(gè)隱藏的input

              name='hide'
          onChange={() => {
          }}
          disabled={true}
          border={false}
          style={{display: 'none'}}/>

          網(wǎng)絡(luò)請(qǐng)求封裝

          Taro框架自帶了 Taro.request 可以用來(lái)請(qǐng)求,不過(guò)我用的時(shí)候很奇怪一直提示跨域,因?yàn)榍捌跁r(shí)間很趕,我就沒(méi)去深入,直接換成我之前vue項(xiàng)目封裝好的axios,果然還是axios好用~

          (不過(guò)之后做成小程序的話,應(yīng)該還是得重構(gòu)一下,據(jù)說(shuō)小程序不支持formdata)

          封裝useState

          感謝「前端帶師 coppy」提供的代碼~

          import?{useState}?from?'react'

          export?default?function?useYourState<T?extends?{}>(state:?T):?[T,?(state:?Partial)?=>?void]?{
          ??const?[_state,?_setState]?=?useState(state);
          ??return?[
          ????_state,
          ????(state:?Partial)?=>?{
          ??????_setState((_state)?=>?{
          ????????return?{
          ??????????..._state,
          ??????????...state
          ????????};
          ??????});
          ????}
          ??];
          }

          這樣就不需要每次setState都需要加...state

          使用前:

          import?{useState}?from?'react'

          export?const?LoginPage?=?observer(()?=>?{
          ??const?[state,?setState]?=?useState({
          ????username:?'',
          ????password:?'',
          ??})
          ??
          ??setState({
          ??????...state,
          ??????username:?'',?password:?''
          ??})
          }

          使用后:

          import?useYourState?from?"@/utils/coppy_state";

          export?const?LoginPage?=?observer(()?=>?{
          ??const?[state,?setState]?=?useYourState({
          ????username:?'',
          ????password:?'',
          ??})
          ??
          ??setState({
          ??????username:?'',?password:?''
          ??})
          }

          生產(chǎn)力獲得了提高~

          全局狀態(tài)管理

          沒(méi)去用大名鼎鼎的redux,轉(zhuǎn)而使用比較簡(jiǎn)單的mobx

          但是找到的例子文檔都不太行(舉例,官方中文文檔:https://cn.mobx.js.org/)

          最終還是尋求「前端帶師」的幫助,搞定了

          坑點(diǎn):

          • store現(xiàn)在沒(méi)法用裝飾器了,用這個(gè)makeAutoObservable
          • 不需要全局provider
          • Taro官網(wǎng)和例子可以說(shuō)是史上最坑,千萬(wàn)別被騙了,地址:https://taro-docs.jd.com/taro/docs/mobx/
          • 請(qǐng)用最新版的mobx和mobx-react-lite,別用Taro官網(wǎng)那個(gè)4.8版本,太老了沒(méi)用

          代碼

          不需要全局provider包裝了,直接用全局變量,當(dāng)然也可以用React Context

          store定義

          import?{makeAutoObservable}?from?"mobx";
          import?{User}?from?"@/models/user";
          import?*?as?auth?from?'@/utils/auth'

          export?class?UserStore?{
          ??isLogin?=?false
          ??user:?User?|?null?=?null
          ??token?=?''

          ??constructor()?{
          ????makeAutoObservable(this)
          ??}

          ??login(user:?User,?token:?string)?{
          ????this.user?=?user
          ????this.token?=?token
          ????this.isLogin?=?true

          ????//?保存登錄數(shù)據(jù)到本地
          ????auth.login(token,?user.username)
          ??}

          ??logout()?{
          ????this.isLogin?=?false
          ????this.user?=?null
          ????this.token?=?''

          ????auth.logout()
          ??}
          }

          export?const?myUserStore?=?new?UserStore()

          組件使用

          import {View} from "@tarojs/components"
          import {AtButton} from "taro-ui";
          import {observer} from "mobx-react-lite";
          import {myUserStore} from "@/store/user";
          import Taro from "@tarojs/taro";
          import {useEffect} from "react";

          export const UserPage = observer(() => {
          useEffect(() => {
          if (!myUserStore.isLogin) {
          Taro.redirectTo({url: '/pages/user/login'})
          }
          }, [])

          return (

          用戶中心

          用戶名:{myUserStore.user?.first_name}

          退出登錄

          )

          function logout() {
          myUserStore.logout()
          Taro.reLaunch({url: '/pages/index/index'})
          }
          })

          export default UserPage

          參考資料

          • 官網(wǎng)文檔:https://mobx.js.org/react-integration.html
          • 項(xiàng)目地址:https://github.com/mobxjs/mobx/tree/main/packages/mobx-react
          • Mobx React 初學(xué)者入門指南(掘金):https://juejin.cn/post/6844903831726211079
          • mobx 在 react 中的 類組件、函數(shù)組件、配合 hooks 的使用:https://juejin.cn/post/6873794258743066632#heading-2

          JSON反序列化class

          使用這個(gè)庫(kù):https://github.com/typestack/class-transformer

          model定義,這個(gè)定義可以用JSON來(lái)生成,有很多在線工具,比如:https://apihelper.jccore.cn/jsontool

          export?class?User?{
          ??username:?string
          ??first_name:?string
          ??last_name:?string
          ??email:?string
          ??date_joined:?string
          }

          注意項(xiàng)目主頁(yè)上的文檔也是過(guò)期了的,plainToClass方法已過(guò)期,得用這個(gè)方法:plainToInstance

          import?{plainToInstance}?from?"class-transformer";

          const?user?=?plainToInstance(User,?res.data.user)
          myUserStore.login(user,?res.data.token)


          瀏覽 117
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产高潮一区 | 午夜操逼视频网 | 一級免費网站 | 久久黄色高清视频 | 欧美日韩aa|