一緒に書く習慣を身につけましょう!「ナゲッツデイリーニュープラン・4月アップデートチャレンジ」に参加した初日です。クリックしてイベントの詳細をご覧ください。
まずはこれです
私の友人は、reactを使ってフロントエンドを長い間開発しておらず、いくつかの単純な関数やページは大きな問題ではありません。少し前React
に18がリリースされ、彼はそれを使って手を一緒に練習する新しいプロジェクトをcreate-react-app
作成しましたが、あらゆる種類の問題に遭遇した人は誰でも助けてください。次に話し合うことがいくつかあります。簡単に思えますが、正しいです。初心者がつまずくための小さな問題。
react
私は18歳ですが、なぜReactDom.render
ですか?
create-react-app
新しく作成されたプロジェクトは、次のように引き続き使用さReactDom.render
れます。
import React from 'react'
import ReactDOM from 'react-dom' //《----------react 17使用的ReactDOM
import App from './App'
import './index.css'
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
)
复制代码
一般的なセマンティクス:関数
ReactDOM
を使用して、コンポーネントを''でノードにレンダリングします。render
JSX Elements
id
root
dom
次にreact 18
、新しい書き込み方法を使用して変換します
react 18
かわった
//index.tsx
import React from 'react'
import { createRoot } from 'react-dom/client' //《----------react 18使用的ReactDOM/client中的createRoot
import App from './App'
import './index.css'
function render() {
const root = createRoot(document.getElementById('root')!)
root.render(
<React.StrictMode>
<App />
</React.StrictMode>
)
}
复制代码
セマンティクスは大まかに次のとおりです。関数
react-dom/client
を使用して'' 'であるノードレンダラーにし、次に関数を使用してそれをレンダリングします。createRoot
id
root
dom
Render
JSX Elements
Reactは18で、React-routerにはv6がありますが、大きく変更されています。使用方法は?
React-router v6
変化は小さくないと言えます。以前のv5
組織ルーティングは次のようになります。
React-routerv5
//app.tsx
import React from 'react'
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
export default () => {
return (
<Router>
<Switch>
<Route path="/" component={Login} />
<Route path="/pageCenter" component={PageCenter} />
</Switch>
</Router>
)
}
)
复制代码
PageCenter
これは私たちのページコンポーネントであり、一般的にここに実装されています嵌套路由
。
//PageCenter.tsx
import React from 'react'
import { Route, Switch } from "react-router-dom";
export default () => {
return (
<>
<Switch>
<Route path="/" component={Login} />
<Route path="/pageCenter" component={PageCenter} />
</Switch>
<>
)
}
)
复制代码
em ~~~~、app.tsxに実装されているトップレベルのルーティングと同じ行にあります。
v5ルーティングの波がどのように編成されているかを評価します
tsx
文件大臃肿:每配置一个路由,就写一个Route
组件,我个人是不喜欢的,我不希望我的tsx
的代码太多,这是我的喜好,为了阅读起来容易,清晰。- 项目的文件夹结构复杂嵌套:顶层路由和嵌套子路由配置分离,直接影响了工程项目中对项目的文件夹结构的编排。因为不能够很直接理清页面组件间的组织关系,不理清会很混乱,维护难度加大,所以理清关系就落在了
项目的文件夹结构
设计了,这就会导致项目的文件夹结构
随着v5 路由的组织方式
的复杂而复杂。
React-router v6
可能是因为 v5 的种种原因,才导致 v6 的变化那么大,最突出便是:
- v6 痛快的推出了配置式路由:一个简单的配置对象,充分描述出了路由的样子和组织关系,痛快~~~。
- 简洁的路由嵌套方式:仅仅在配置了嵌套路由组件中,使用新推出的标签就搞定了,优雅~~~。
不过~~~,也有一些破坏性的改变,让我措手不及,比如:
- 路由拦截无了!!!:拦截啊可是,怎么没有了,这。。。
withRouter
无了!!!:函数组件我能用hook
搞搞,类组件咋办,这。。。
em ~~~没事 repect,毕竟进步嘛,怎么会没代价呢,没有咱就自己搞被,不坐车就不会走了么?
我为此写了一个库r6helper,尽可能的弥补了升级 v6 带来的影响
- 拦截,安排上了。
withRouter
,安排上了。
路由好了,那么路由懒加载得有吧,怎么搞?
方式还是依然是通过 React.lazy
配合import
的动态引入,代码如下。
const Login = React.lazy(() => import('./login'))
复制代码
次にReact.Suspense
、この遅延読み込みコンポーネントをラップする必要があります。そうしないと、エラーが報告されます。私の友人は長い間立ち往生しています。。。、その理由は、レイジーコンポーネントの周りにレイヤーをラップするのを忘れたためですReact.Suspense
。
<React.Suspense fallback={<>...</>}>{<Login />}</React.Suspense>
复制代码
ただし、私の友人は、ページを追加するたびに、lazy
インポートコンポーネントとSuspense
パッケージを作成し、さらにページが増えると、コードは次のようになると言っていました。
const Login = React.lazy(() => import('./pages/login'))
const Page1 = React.lazy(() => import('./pages/page1'))
const Page2 = React.lazy(() => import('./pages/page2'))
const Page3 = React.lazy(() => import('./pages/page3'))
const Page4 = React.lazy(() => import('./pages/page4'))
const Page5 = React.lazy(() => import('./pages/page5'))
...
export default () => {
return useRoutes([
{
path: '/',
element: <React.Suspense fallback={<>...</>}>{<Login />}</React.Suspense>
},
{
path: '/page1',
element:<React.Suspense fallback={<>...</>}>{<Page1 />}</React.Suspense>
},
{
path: '/page2',
element: <React.Suspense fallback={<>...</>}>{<Page2 />}</React.Suspense>
},
{
path: '/page3',
element: <React.Suspense fallback={<>...</>}>{<Page3 />}</React.Suspense>
},
{
path: '/page4',
element: <React.Suspense fallback={<>...</>}>{<Page4 />}</React.Suspense>
},
{
path: '/page5',
element: <React.Suspense fallback={<>...</>}>{<Page5 />}</React.Suspense>
},
{
path: '/404',
element: <div>not found</div>
},
])
}
复制代码
これは非常に冗長に見えます。繰り返されるコードがたくさんあります。彼がそれを最適化するのを手伝ってくれることを願っています。em~~~問題ありません、全体を開いてください。
コードを最適化する
主に2つの側面から:
- コンポーネント
lazy
のインポート - その後、
Suspense
ラップ
統一された入り口
まず、ページコンポーネントがpages
パスの下に配置され、次にインポートするように指示されます。統合管理のためindex
に、フォルダーの下に1つ追加します。pages
// 文件:pages/index.ts
export Login = React.lazy(() => import('./pages/login'))
export Page1 = React.lazy(() => import('./pages/page1'))
export Page2 = React.lazy(() => import('./pages/page2'))
export Page3 = React.lazy(() => import('./pages/page3'))
export Page4 = React.lazy(() => import('./pages/page4'))
export Page5 = React.lazy(() => import('./pages/page5'))
复制代码
次に、前のインポートコードをリファクタリングします。
const { Login, Page1, Page2, Page3, Page4, Page5 } from './pages'
复制代码
パッケージングコンポーネントをカプセル化し、複数のタイプをサポート
複数のタイプをラップできるコンポーネントを記述します。これらはすべてラップできます。
- コンポーネントを含む:関数コンポーネントとクラスコンポーネント。
- 怠惰なコンポーネント。
- jsx要素。
その場合、コードは次のようになります。
// 加载异步组件的loading
export const wrapper = (Child: any, cutonFallBack?: CutonFallBackT) => {
// 判断jsx
if (Child.type && !Child._init && !Child._payload) {
return Child
} else {
// 判断是否为clas和function组件
if (typeof Child === 'function') {
return <Child></Child>
} else {
// 判断是否为lazy组件
return (
<React.Suspense fallback={cutonFallBack || <>...</>}>
{<Child></Child>}
</React.Suspense>
)
}
}
}
复制代码
次に、全体的なリファクタリングされたコードはおおよそ次のようになります
const { Login, Page1, Page2, Page3, Page4, Page5 } from './pages'
...
export default () => {
return useRoutes([
{
path: '/',
element: wrapper(Login)
},
{
path: '/page1',
element: wrapper(Page1)
},
{
path: '/page2',
element: wrapper(Page2)
},
{
path: '/page3',
element: wrapper(Page3)
},
{
path: '/page4',
element: wrapper(Page4)
},
{
path: '/page5',
element: wrapper(Page5)
},
{
path: '/404',
element: wrapper(<div>not found</div>)
},
])
}
复制代码
em ~~~シンプルで気取らないですが、コードはずっと快適に見えます。私の友人は、私がたくさんの良いことを学んだことを嘆きました。これが基本的な操作、233333だと思います。