国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

免費(fèi)做明信片的網(wǎng)站新區(qū)快速seo排名

免費(fèi)做明信片的網(wǎng)站,新區(qū)快速seo排名,自己做的網(wǎng)站怎么發(fā)布到網(wǎng)上,企業(yè)咨詢(xún)管理公司是干嘛的文章目錄 1、項(xiàng)目搭建1、創(chuàng)建項(xiàng)目1.2 配置項(xiàng)目1.2.1 更換icon1.2.2 更換項(xiàng)目名稱(chēng)1.2.1 配置項(xiàng)目別名 1.3 代碼規(guī)范1.3.1 集成editorconfig配置1.3.2 使用prettier工具 1.4 項(xiàng)目結(jié)構(gòu)1.5 對(duì)css進(jìn)行重置1.6 注入router1.7 定義TS組件的規(guī)范1.8 創(chuàng)建代碼片段1.9 二級(jí)路由和懶加載1.…

文章目錄

  • 1、項(xiàng)目搭建
    • 1、創(chuàng)建項(xiàng)目
    • 1.2 配置項(xiàng)目
      • 1.2.1 更換icon
      • 1.2.2 更換項(xiàng)目名稱(chēng)
      • 1.2.1 配置項(xiàng)目別名
    • 1.3 代碼規(guī)范
      • 1.3.1 集成editorconfig配置
      • 1.3.2 使用prettier工具
    • 1.4 項(xiàng)目結(jié)構(gòu)
    • 1.5 對(duì)css進(jìn)行重置
    • 1.6 注入router
    • 1.7 定義TS組件的規(guī)范
    • 1.8 創(chuàng)建代碼片段
    • 1.9 二級(jí)路由和懶加載
    • 1.10 redux-reduxtk
    • 1.10 axios的封裝
  • 1.11 類(lèi)組件和TS的結(jié)合
    • 1.12 redux和ts的結(jié)合

1、項(xiàng)目搭建

1、創(chuàng)建項(xiàng)目

  • 1、該項(xiàng)目使用的是ts創(chuàng)建的 所以需要加上--template typescript
    • create-react-app kiki_ts_react_music --template typescript
  • 2、整理項(xiàng)目結(jié)構(gòu) 刪除一些自己用不到的文件
  • 在這里插入圖片描述
    在這里插入圖片描述

1.2 配置項(xiàng)目

1.2.1 更換icon

在這里插入圖片描述

1.2.2 更換項(xiàng)目名稱(chēng)

在index.html文件里面

在這里插入圖片描述

1.2.1 配置項(xiàng)目別名

  • 1、npm i -D @craco/craco
  • 2、在根文件創(chuàng)建 craco.config.ts
const path = require("path");
const CracoLessPlugin = require("craco-less");// path.resolve返回當(dāng)前文件的絕對(duì)路徑 拼接+dir
const resolve = (dir) => path.resolve(__dirname, dir);
module.exports = {plugins: [{ plugin: CracoLessPlugin }],webpack: {alias: {"@": resolve("src"),},},
};
  • 3、修改tsconfig.json
    在這里插入圖片描述
    "baseUrl": ".","paths": {"@/*": ["src/*"]}
  • 4、修改 package.json
  "scripts": {"start": "craco start","build": "craco build","test": "craco test","eject": "react-scripts eject"},

1.3 代碼規(guī)范

1.3.1 集成editorconfig配置

EditorConfig 有助于為不同 IDE 編輯器上處理同一項(xiàng)目的多個(gè)開(kāi)發(fā)人員維護(hù)一致的編碼風(fēng)格。

  • 1、在根目錄下創(chuàng)建.editorconfig文件
# http://editorconfig.orgroot = true[*] # 表示所有文件適用
charset = utf-8 # 設(shè)置文件字符集為 utf-8
indent_style = space # 縮進(jìn)風(fēng)格(tab | space)
indent_size = 2 # 縮進(jìn)大小
end_of_line = lf # 控制換行類(lèi)型(lf | cr | crlf)
trim_trailing_whitespace = true # 去除行尾的任意空白字符
insert_final_newline = true # 始終在文件末尾插入一個(gè)新行[*.md] # 表示僅 md 文件適用以下規(guī)則
max_line_length = off
trim_trailing_whitespace = false

**同時(shí)需要安裝插件 **EditorConfig for VS Code

在這里插入圖片描述

1.3.2 使用prettier工具

Prettier 是一款強(qiáng)大的代碼格式化工具,支持 JavaScript、TypeScript、CSS、SCSS、Less、JSX、Angular、Vue、GraphQL、JSON、Markdown 等語(yǔ)言,基本上前端能用到的文件格式它都可以搞定,是當(dāng)下最流行的代碼格式化工具。

在這里插入圖片描述
在這里插入圖片描述

在這里插入圖片描述

  • 1.安裝prettier

    npm install prettier -D

  • 2、配置.prettierrc文件:在根目錄下創(chuàng)建該文件
    在這里插入圖片描述

{"useTabs": false,"tabWidth": 2,"printWidth": 80,"singleQuote": true,"trailingComma": "none","semi": false
}
  • 3、創(chuàng)建.prettierignore忽略文件 在根目錄下
/dist/*
.local
.output.js
/node_modules/****/*.svg
**/*.sh/public/*
  • 4、在package.json中配置一個(gè)scripts:
    "prettier": "prettier --write ."

執(zhí)行 npm run prettier就會(huì)將項(xiàng)目全部按照prettier的配置進(jìn)行格式化

1.4 項(xiàng)目結(jié)構(gòu)

在這里插入圖片描述

1.5 對(duì)css進(jìn)行重置

  • 1、下載normalize.css
    cnpm install normalize.css
    在index.tsx里面引入import 'normalize.css'

  • 2、使用less
    cnpm install craco-less

const path = require('path')
const CracoLessPlugin = require('craco-less')const resolve = (dir) => path.resolve(__dirname, dir)
module.exports = {plugins: [{ plugin: CracoLessPlugin }],webpack: {alias: {'@': resolve('src')}}
}

在這里插入圖片描述

  • 3、配置自定義的css
    在這里插入圖片描述
    最后都在index.jsx中引入
import 'normalize.css'
import '@/assets/css/index.less'

1.6 注入router

npm install react-router-dom

  • 在tsx中 使用到dom的頁(yè)面都需要引入import React from 'react'

  • router/index.tsx

import React from 'react'
import type { RouteObject } from 'react-router-dom'
import Discover from '@/views/discover'
import Mime from '@/views/mime'const routes: RouteObject[] = [{ path: '/', element: <Mime /> },{ path: '/discover', element: <Discover /> }
]export default routes
  • index.tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from '@/App'
import { BrowserRouter } from 'react-router-dom'
import 'normalize.css'
import '@/assets/css/index.less'const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(<BrowserRouter><App /></BrowserRouter>
)
  • index.tsx
import React, { Suspense } from 'react'
import { Link, useRoutes } from 'react-router-dom'
import routes from './router'function App() {return (<div className="App"><header className="App-header"><h1>hahah</h1><Link to="/discover">發(fā)現(xiàn)音樂(lè)</Link><Suspense fallback="正在加載">{useRoutes(routes)}</Suspense></header></div>)
}export default App

1.7 定義TS組件的規(guī)范

import React, { memo } from 'react'
import type { ReactNode } from 'react'// 定義傳進(jìn)來(lái)的props類(lèi)型
interface IProps {// 在之前的版本props默認(rèn)會(huì)有children是插槽 在后來(lái)取消了得自己寫(xiě)children?: ReactNodename?: stringage?: number
}const Download: React.FC<IProps> = (props) => {return (<div>{props.children}<h1>{props.age}</h1><h1>{props.name}</h1></div>)
}export default memo(Download)
import React, { Suspense } from 'react'
import { Link, useRoutes } from 'react-router-dom'
import routes from './router'
import Download from './views/download'function App() {return (<div className="App"><header className="App-header"><h1>hahah</h1><Link to="/discover">發(fā)現(xiàn)音樂(lè)</Link><Download name="kiki"><h1>我是downLoad的插槽</h1></Download><Suspense fallback="正在加載">{useRoutes(routes)}</Suspense></header></div>)
}export default App

1.8 創(chuàng)建代碼片段

首選項(xiàng)=>設(shè)置代碼片段=>react-ts
在這里插入圖片描述

生成代碼片段的網(wǎng)站
https://snippet-generator.app/?description=&tabtrigger=&snippet=&mode=vscode
在這里插入圖片描述

import React, { memo } from 'react'
import type { FC, ReactNode } from 'react'interface IProps {children?: ReactNode
}const Template: FC<IProps> = () => {return <div>Template</div>
}export default memo(Template)

1.9 二級(jí)路由和懶加載

  • discover頁(yè)面
import React, { memo, Suspense } from 'react'
import type { FC, ReactNode } from 'react'
import { Outlet, Link } from 'react-router-dom'interface IProps {children?: ReactNode
}const Discover: FC<IProps> = () => {return (<div><div><Link to="/discover/recommend">推薦</Link><Link to="/discover/ranking">排行榜</Link><Link to="/discover/songs">歌單</Link><Link to="/discover/djradio">主播電臺(tái)</Link><Link to="/discover/artist">歌手</Link><Link to="/discover/album">新碟上架</Link></div>{/* 二級(jí)路由也可以用suspense */}<Suspense fallback="正在加載"><Outlet /></Suspense></div>)
}export default memo(Discover)
  • App.jsx
import React, { Suspense } from 'react'
import { Link, useRoutes } from 'react-router-dom'
import routes from './router'
import Download from './views/download'function App() {return (<div className="App"><div className="nav"><Link to="/discover">發(fā)現(xiàn)音樂(lè)</Link><Link to="/mine">我的音樂(lè)</Link><Link to="/focus">關(guān)注</Link><Link to="/download">下載客戶端</Link></div><Suspense fallback="正在加載">{useRoutes(routes)}</Suspense><div className="main"></div></div>)
}export default App

在這里插入圖片描述

1.10 redux-reduxtk

cnpm install @reduxjs/toolkit react-redux

  • index.tsx 提供Provide
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from '@/App'
import { BrowserRouter } from 'react-router-dom'
import { Provider } from 'react-redux'
import 'normalize.css'
import '@/assets/css/index.less'
import store from './store'const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement)
root.render(<Provider store={store}><BrowserRouter><App /></BrowserRouter></Provider>
)
  • store/index.ts
import { configureStore } from '@reduxjs/toolkit'
import { useSelector, useDispatch, TypedUseSelectorHook } from 'react-redux'
import counterReducer from './modules/counter'const store = configureStore({reducer: {counter: counterReducer}
})// 獲取函數(shù)的返回類(lèi)型
type GetStateFnType = typeof store.getState
// 獲取函數(shù)返回類(lèi)型的類(lèi)型
type IRootState = ReturnType<GetStateFnType>
type DispatchType = typeof store.dispatchexport const useAppSelector: TypedUseSelectorHook<IRootState> = useSelector
export const useAppDisPatch: () => DispatchType = useDispatchexport default store
  • store/count.ts
import { createSlice } from '@reduxjs/toolkit'const counterSlice = createSlice({name: 'counter',initialState: {count: 1,message: 'hello'},reducers: {changeMessageAction(state, { payload }) {state.message = payload}}
})export const { changeMessageAction } = counterSlice.actions
export default counterSlice.reducer
  • 使用的頁(yè)面
import React, { memo, Suspense } from 'react'
import type { FC, ReactNode } from 'react'
import { Outlet, Link } from 'react-router-dom'
import { useAppDisPatch, useAppSelector } from '@/store'
import { shallowEqual } from 'react-redux'
import { changeMessageAction } from '@/store/modules/counter'interface IProps {children?: ReactNode
}const Discover: FC<IProps> = () => {const { count, message } = useAppSelector((state) => ({count: state.counter.count,message: state.counter.message}),shallowEqual)const dispatch = useAppDisPatch()const changeMessage = (message: string) => {dispatch(changeMessageAction(message))}return (<div><div>{count}=={message}<button onClick={() => changeMessage('修改message')}>修改message</button><Link to="/discover/recommend">推薦</Link><Link to="/discover/ranking">排行榜</Link><Link to="/discover/songs">歌單</Link><Link to="/discover/djradio">主播電臺(tái)</Link><Link to="/discover/artist">歌手</Link><Link to="/discover/album">新碟上架</Link></div>{/* 二級(jí)路由也可以用suspense */}<Suspense fallback="正在加載"><Outlet /></Suspense></div>)
}export default memo(Discover)

1.10 axios的封裝

在這里插入圖片描述

  • request/index.ts
import axios from 'axios'
import type { AxiosInstance } from 'axios'
import type { HYRequestConfig } from './type'// 攔截器: 蒙版Loading/token/修改配置/*** 兩個(gè)難點(diǎn):*  1.攔截器進(jìn)行精細(xì)控制*    > 全局?jǐn)r截器*    > 實(shí)例攔截器*    > 單次請(qǐng)求攔截器**  2.響應(yīng)結(jié)果的類(lèi)型處理(泛型)*/class HYRequest {instance: AxiosInstance// request實(shí)例 => axios的實(shí)例constructor(config: any) {this.instance = axios.create(config)// 每個(gè)instance實(shí)例都添加攔截器this.instance.interceptors.request.use((config) => {// loading/tokenreturn config},(err) => {return err})this.instance.interceptors.response.use((res) => {return res.data},(err) => {return err})// 針對(duì)特定的hyRequest實(shí)例添加攔截器this.instance.interceptors.request.use(config.interceptors?.requestSuccessFn,config.interceptors?.requestFailureFn)this.instance.interceptors.response.use(config.interceptors?.responseSuccessFn,config.interceptors?.responseFailureFn)}// 封裝網(wǎng)絡(luò)請(qǐng)求的方法// T => IHomeDatarequest<T = any>(config: HYRequestConfig<T>) {// 單次請(qǐng)求的成功攔截處理if (config.interceptors?.requestSuccessFn) {config = config.interceptors.requestSuccessFn(config)}// 返回Promisereturn new Promise<T>((resolve, reject) => {this.instance.request<any, T>(config).then((res) => {// 單詞響應(yīng)的成功攔截處理if (config.interceptors?.responseSuccessFn) {res = config.interceptors.responseSuccessFn(res)}resolve(res)}).catch((err) => {reject(err)})})}get<T = any>(config: HYRequestConfig<T>) {return this.request({ ...config, method: 'GET' })}post<T = any>(config: HYRequestConfig<T>) {return this.request({ ...config, method: 'POST' })}delete<T = any>(config: HYRequestConfig<T>) {return this.request({ ...config, method: 'DELETE' })}patch<T = any>(config: HYRequestConfig<T>) {return this.request({ ...config, method: 'PATCH' })}
}export default HYRequest
  • request/type.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios'// 針對(duì)AxiosRequestConfig配置進(jìn)行擴(kuò)展
export interface HYInterceptors<T = AxiosResponse> {requestSuccessFn?: (config: AxiosRequestConfig) => AxiosRequestConfigrequestFailureFn?: (err: any) => anyresponseSuccessFn?: (res: T) => TresponseFailureFn?: (err: any) => any
}export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {interceptors?: HYInterceptors<T>
}
  • config/index.ts
import type { AxiosRequestConfig, AxiosResponse } from 'axios'// 針對(duì)AxiosRequestConfig配置進(jìn)行擴(kuò)展
export interface HYInterceptors<T = AxiosResponse> {requestSuccessFn?: (config: AxiosRequestConfig) => AxiosRequestConfigrequestFailureFn?: (err: any) => anyresponseSuccessFn?: (res: T) => TresponseFailureFn?: (err: any) => any
}export interface HYRequestConfig<T = AxiosResponse> extends AxiosRequestConfig {interceptors?: HYInterceptors<T>
}

環(huán)境變量也可以通過(guò)配置文件 但是前面需要加上REACT_APP_…

在這里插入圖片描述

  • service/index.ts
import { BASE_URL, TIME_OUT } from './config'
import HYRequest from './request'const hyRequest = new HYRequest({baseURL: BASE_URL,timeout: TIME_OUT,interceptors: {requestSuccessFn: (config: any) => {return config}}
})export default hyRequest

在這里插入圖片描述

  • 使用的頁(yè)面
import React, { memo, useEffect, useState } from 'react'
import type { FC, ReactNode } from 'react'
import hyRequest from '@/service'interface IProps {children?: ReactNode
}export interface IBannerData {imageUrl: stringtargetId: numbertargetType: numbertitleColor: stringtypeTitle: stringurl: stringexclusive: booleanscm: stringbannerBizType: string
}const Recommend: FC<IProps> = () => {const [banners, setBanners] = useState<IBannerData[]>([])// 測(cè)試網(wǎng)絡(luò)請(qǐng)求useEffect(() => {hyRequest.get({url: '/banner'}).then((res) => {setBanners(res.banners)})}, [])return (<div>{banners.map((item, index) => {return <div key={index}>{item.imageUrl}</div>})}</div>)
}export default memo(Recommend)
  • 可以在這個(gè)頁(yè)面自動(dòng)生成類(lèi)型定義
    https://transform.tools/json-to-typescript

1.11 類(lèi)組件和TS的結(jié)合

import React, { PureComponent } from 'react'
/*** state:* props:*/interface IProps {name: stringage?: number
}interface IState {message: stringcounter: number
}class Demo02 extends PureComponent<IProps, IState> {name = 'aaaa'state = {message: 'Hello World',counter: 99}// getSnapshotBeforeUpdate() {//   return { address: '廬山' }// }// componentDidUpdate(//   prevProps: Readonly<IProps>,//   prevState: Readonly<IState>,//   snapshot?: ISnapshot | undefined// ): void {}// constructor(props: IProps) {//   super(props)//   // this.state = {//   //   message: 'Hello World',//   //   counter: 100//   // }// }render(): React.ReactNode {return (<div>name: {this.props.name}age: {this.props.age}message: {this.state.message}counter: {this.state.counter}</div>)}
}export default Demo02

1.12 redux和ts的結(jié)合

import { createSlice, PayloadAction } from '@reduxjs/toolkit'interface IState {count: numbermessage: stringaddress: stringheight: numberdirection: 'left' | 'right' | 'up' | 'down'names: string[]
}const initialState: IState = {count: 100,message: 'Hello Redux',address: '廣州市',height: 1.88,direction: 'left',names: []
}const counterSlice = createSlice({name: 'counter',initialState,reducers: {changeMessageAction(state, { payload }: PayloadAction<string>) {state.message = payload}}
})export const { changeMessageAction } = counterSlice.actions
export default counterSlice.reducer
http://aloenet.com.cn/news/39371.html

相關(guān)文章:

  • 小型企業(yè)網(wǎng)站的設(shè)計(jì)與實(shí)現(xiàn)搜索引擎營(yíng)銷(xiāo)的典型案例
  • 免費(fèi)網(wǎng)站建設(shè)步驟百度收錄權(quán)重
  • 網(wǎng)站投票系統(tǒng) js產(chǎn)品推廣方案范文500字
  • 惠州做網(wǎng)站的公司百度指數(shù)怎么看排名
  • 建設(shè)一個(gè)怎樣的自己的網(wǎng)站首頁(yè)鄭州粒米seo顧問(wèn)
  • 建設(shè)電影網(wǎng)站廣告哪里找搜索引擎推廣法
  • 做app+的模板下載網(wǎng)站短視頻精準(zhǔn)獲客
  • 武漢網(wǎng)站制2023年8月份新冠
  • 佛山新網(wǎng)站制作咨詢(xún)東莞全網(wǎng)推廣
  • 深圳做網(wǎng)站的公司搜行者seo如何制作微信小程序店鋪
  • 公司網(wǎng)站 開(kāi)源深圳seo專(zhuān)家
  • 供應(yīng)鏈管理軟件十大排名seo顧問(wèn)培訓(xùn)
  • 網(wǎng)站管理員登錄哪有學(xué)電腦培訓(xùn)班
  • 蘇州個(gè)人網(wǎng)站建設(shè)信息推廣的方式有哪些
  • 做一個(gè)wordpress模板關(guān)鍵詞首頁(yè)排名優(yōu)化平臺(tái)
  • 西安有什么網(wǎng)站網(wǎng)絡(luò)輿情監(jiān)測(cè)中心
  • 建站的步驟有哪些杭州網(wǎng)站
  • php網(wǎng)站開(kāi)發(fā)代碼東莞做網(wǎng)站最好的是哪家
  • 邯鄲網(wǎng)站制作多少錢(qián)蘇州網(wǎng)站建設(shè)制作公司
  • 貴州省城鄉(xiāng)和建設(shè)廳網(wǎng)站seo優(yōu)化的作用
  • 游戲網(wǎng)站風(fēng)格dz論壇seo
  • 阿里云 做購(gòu)物網(wǎng)站網(wǎng)站seo是什么平臺(tái)
  • 上海網(wǎng)站建設(shè)心得win10一鍵優(yōu)化工具
  • 免費(fèi)做網(wǎng)站的軟件小廣告設(shè)計(jì)
  • 上市公司做網(wǎng)站源碼網(wǎng)站
  • 做網(wǎng)站用什么語(yǔ)言最好seo優(yōu)化設(shè)計(jì)
  • 陜西 汽車(chē) 網(wǎng)站建設(shè)網(wǎng)頁(yè)制作源代碼
  • 商城開(kāi)發(fā)價(jià)格服務(wù)企業(yè)網(wǎng)站優(yōu)化服務(wù)公司
  • 移動(dòng)網(wǎng)站制作價(jià)格安裝百度到手機(jī)桌面
  • 網(wǎng)站是先解析后備案嗎免費(fèi)投放廣告平臺(tái)