国产91在线无码_少妇人妻无码高清_91人妻中文字幕无码专区在线_国产福利在线播放_免费 无码 国产成年视频网站

前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?

前言

筆者上一篇文章:

前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?

主要寫了typescript的用法和核心知識點總結(jié), 這篇文章將通過一個實際的前端案例來教大家如何在項目中使用typescript.

你將收獲

  • 如何使用umi快速搭建一個基于React antd typescript的前端項目
  • 中后臺前端項目的目錄和ts文件劃分
  • 在React組件中使用typescript
  • 在工具庫中使用typescript
  • 互聯(lián)網(wǎng)黑白墻案例分析

正文

在開始文章之前, 我們先看一下企業(yè)黑白墻項目的演示:

前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?

趣談前端

(注: 本文僅針對項目剖析和學(xué)習(xí)使用, 不做任何商業(yè)用途)

該項目是一個響應(yīng)式網(wǎng)站, 針對PC端和H5均做了一定的適配, 接下來我們將正對該網(wǎng)站做一次typescript剖析.

由上面的gif可以看出網(wǎng)站的信息結(jié)構(gòu)圖大致如下:

前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?

趣談前端

接下來進入我們的正文.

1. 使用umi快速搭建一個基于React antd typescript的前端項目

umi是一個功能強大且開箱即用的企業(yè)級項目腳手架, 這里筆者直接采用umi來創(chuàng)建一個ts項目, 具體方式如下:

// 1.創(chuàng)建項目空目錄$ mkdir ts-react && cd ts-react// 2.創(chuàng)建項目yarn create @umijs/umi-app// 3.安裝項目依賴yarn

用umi開發(fā)只需要簡單的3個命令即可, 值得注意的是, 在執(zhí)行步驟2時會在命令行出現(xiàn)如下交互選項:

前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?

主要是讓我們選擇創(chuàng)建的項目類型的, 這里我們選typescript和antd即可, 有關(guān)如何創(chuàng)建可交互的命令行工具, 在筆者的 基于react/vue生態(tài)的前端集成解決方案探索與總結(jié) 中有介紹, 感興趣的可以學(xué)習(xí)交流.

經(jīng)過以上的步驟我們就初步搭建了一個支持react typescript antd技術(shù)棧的項目骨架.

2. 中后臺前端項目的目錄和ts文件劃分

我們先看看本次研究的項目的目錄劃分:

ts-react ├─ src │ ├─ assets │ │ └─ yay.jpg │ ├─ components │ │ └─ PublicModal │ │ ├─ index.css │ │ ├─ index.tsx │ │ └─ type.ts │ ├─ layouts │ │ ├─ __tests__ │ │ │ └─ index.test.tsx │ │ ├─ index.css │ │ └─ index.tsx │ ├─ locales │ │ └─ en-US.ts │ ├─ models │ ├─ pages │ │ ├─ __tests__ │ │ │ ├─ __mocks__ │ │ │ │ └─ umi-plugin-locale.ts │ │ │ └─ index.test.tsx │ │ ├─ about │ │ │ ├─ components │ │ │ ├─ index.d.ts │ │ │ ├─ index.less │ │ │ └─ index.tsx │ │ ├─ index.css │ │ ├─ index.tsx │ │ ├─ innerRec.tsx │ │ └─ list.tsx │ ├─ utils │ │ ├─ tool.ts │ │ └─ type.ts │ ├─ app.ts │ └─ global.css ├─ global.d.ts ├─ package.json ├─ readme.md ├─ tsconfig.json └─ typings.d.ts

我們從外往里看, 在項目根目錄下有typings.d.tsglobal.d.ts這兩個文件, 前者我們可以放置一些全局的導(dǎo)出模塊,比如css,less, 圖片的導(dǎo)出聲明, 這樣我們就不用一個個的在頁面代碼里再重新聲明了, 如下:

// typings.d.tsdeclare module '*.css';declare module '*.less';declare module "*.png";declare module "*.jpeg";

這樣做我們就能避免在頁面中導(dǎo)入css或者圖片文件時ts報錯的問題了. 對于global.d.ts, 筆者建議放一些全局聲明的變量, 接口等, 比如說Jquery這種第三方庫的聲明, window下全局變量的聲明等.

其次是src目錄,我們具體介紹一下目錄的意義: assets 存放靜態(tài)資源如圖片/視頻/音頻等, 參與webpack的打包過程 layouts 存放公共布局 components 存放全局共同組件 locales 多語言配置目錄 models dva的models文件夾, 處理redux流 pages 存放頁面的目錄, 內(nèi)部可以有頁面組件components, 結(jié)構(gòu)類似于全局的components * utils 存放js工具庫, 請求庫等公共js文件

在了解了上面的目錄和目錄的含義之后, 我們再來看看如何規(guī)劃其中的ts文件.

對于組件庫來說, 其下面的一個子目錄對應(yīng)一個組件, 里面包含必須的樣式文件, 組件tsx文件和組件自有類型文件, 這里命名為type.ts, 專門存放該組件所需要的類型和接口聲明.

同理對于頁面文件夾來說, 也應(yīng)具有類似的結(jié)構(gòu), 就好比上面的about頁面, 包含如下結(jié)構(gòu): components 該頁面專有的組件目錄 index.tsx 關(guān)于頁面的主文件 index.less 關(guān)于頁面的樣式文件 type.ts 關(guān)于頁面的類型和接口聲明文件

還需要說明一點的是, 如果某個頁面有私有的類型或者接口聲明,我們可以直接在文件內(nèi)部去聲明, 沒必要全部都拿到外面去定義和聲明.

目錄規(guī)劃這塊基本完成, 實際情況還是需要根據(jù)自身項目結(jié)構(gòu)來做更合理的劃分, 接下來我們看看具體的typescript在業(yè)務(wù)代碼中的應(yīng)用.

3. 在React組件中使用typescript

這里筆者將會拿該項目的自定義上傳組件以及白名單頁面作為例子, 文件上傳組件筆者將采用SFC(即函數(shù)組件), 白名單頁面將采用類組件, 這樣可以方便大家對這兩中組件開發(fā)模式下的typescript開發(fā)有個全面的認(rèn)知.

3.1 自定義上傳組件開發(fā)

自定義上傳組件我們主要應(yīng)用在發(fā)布模塊, 基于antd進行二次封裝以便能兼容支持antd的Form模型, 如下圖:

前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?

趣談前端

結(jié)合typescript的實現(xiàn)如下:

import React, { useState, useEffect, SFC, ReactNode } from 'react';import { Upload, message } from 'antd';import { LoadingOutlined, PlusOutlined } from '@ant-design/icons';import styles from './index.less';export interface BeforeUploadFunc { (file:File, fileList:FileList): boolean | Promise<File>;}export interface SuccessBack { (url: string): string;}export interface ChangeFunc { (value: string | Array<string>): void;}export interface IProps { action: string; listType?: string; showUploadList?: boolean; headers?: object; beforeUpload?: BeforeUploadFunc; onSuccess?: SuccessBack; withCredentials?: boolean; text?: string | ReactNode; imgUrl?: string; onChange?: ChangeFunc; value?: string;}const UploadCp:SFC<IProps> = (props:IProps) => { const { listType = 'picture-card', showUploadList = false, action = 'http://io.cc.com/api/files/free', headers, beforeUpload = handleBeforeUpload, onSuccess, withCredentials = true, text = '上傳封面', imgUrl, onChange, value } = props const [loading, setLoading] = useState(false) const [imageUrl, setImageUrl] = useState(imgUrl) const handleChange = (info:FileList):void => { // 一些操作 } function handleBeforeUpload(file:File):boolean { const isJpgOrPng = file.type === 'image/jpeg' || file.type === 'image/png'; if (!isJpgOrPng) { message.error('You can only upload JPG/PNG file!'); } const isLt2M = file.size / 1024 / 1024 < 2; if (!isLt2M) { message.error('Image must smaller than 2MB!'); } return isJpgOrPng && isLt2M; } useEffect(() => { !value && setImageUrl(imgUrl) }, [imgUrl, value]) return <Upload name="file" listType={listType} className={styles.avatarUploader} showUploadList={showUploadList} action={action} withCredentials={withCredentials} headers={headers} beforeUpload={beforeUpload} onChange={handleChange} > {(value || imageUrl) ? <img src={value || imageUrl} alt="avatar" style={{ width: '100%' }} alt={text} /> : text} </Upload>}export default UploadCp

以上代碼我們使用了React的函數(shù)組件, React提供了函數(shù)組件的類型SFC, 內(nèi)置了children所以我們不用顯示的再聲明一次. 其他的比如函數(shù)聲明, 泛型接口, 可選類型的設(shè)置等筆者在上一篇文章:

徐小夕:TS核心知識點總結(jié)及項目實戰(zhàn)案例分析

有詳細(xì)介紹.不懂的可以在評論區(qū)與我交流.

3.2 白名單頁面開發(fā)

在了解完函數(shù)式組件如何與typescript搭配使用之后, 我們再來看看類組件. 我們那拿搜索列表頁作為例子來講解:

前端小哥哥:如何使用typescript開發(fā)實戰(zhàn)項目?

代碼如下:

import React from 'react';import { List, Avatar, Button, Skeleton, Tag, Modal } from 'antd';import styles from './index.less';import req from '@/utils/req';export interface IProps extends Location {}interface List { name: string; img: string; desc: string; isLoading?: boolean;}interface LoadingState { initLoading: boolean; loading: boolean;}export interface IState extends LoadingState { data: Array<List>; list: Array<List>;}class LoadMoreList extends React.Component<IProps, IState> { state:IState = { initLoading: true, loading: false, data: [], list: [], }; componentDidMount() { this.getData(); } getData = () => { req.get(`/blackwhite/get?type=${this.props.location.query.type}`).then((res:List) => { this.setState({ initLoading: false, data: res, list: res.slice(0, pageNum) }); }) }; render() { const { initLoading, loading, list, data } = this.state; return // 頁面實現(xiàn)代碼 }}export default LoadMoreList

以上代碼實現(xiàn)了class組件的typescript應(yīng)用, 對于interface類型聲明用到了繼承, 當(dāng)然也可以不用繼承直接寫類型聲明, 這里主要為了學(xué)習(xí)方便. 大家也可以把公用的頁面類型放到單獨的type.ts目錄下復(fù)用.

4. 在工具庫中使用typescript

在掌握了類組件和函數(shù)組件的typescript寫法之后, 我們來說說工具類的typescript編寫方式, 這塊比較簡單, 筆者簡單舉幾個常用工具函數(shù), 將其改造成typescript的模式. 代碼如下:

// utils/tool.ts/* * @Author: Mr Jiang.Xu * @Date: 2019-06-06 11:23:05 * @Last Modified by: Mr Jiang.Xu * @Last Modified time: 2019-06-29 22:33:52 *//** * 識別ie--淺識別 */export const isIe = ():boolean => { let explorer = window.navigator.userAgent; //判斷是否為IE瀏覽器 if (explorer.indexOf("MSIE") >= 0) { return true; }else { return false }}/** * 顏色轉(zhuǎn)換16進制轉(zhuǎn)rgba * @param {String} hex * @param {Number} opacity */export function hex2Rgba(hex:string, opacity:number):string { if(!hex) hex = "#2c4dae"; return "rgba(" parseInt("0x" hex.slice(1, 3)) "," parseInt("0x" hex.slice(3, 5)) "," parseInt("0x" hex.slice(5, 7)) "," (opacity || "1") ")";}// 去除html標(biāo)簽export const htmlSafeStr = (str:string):string => { return str.replace(/<[^>] >/g, "")}interface params { [propertyName: string]: string | number}/* 解析url參數(shù) */export const toParams = (params:params):string => { if(params){ let query = []; for(let key in params){ query.push(`${key}=${params[key]}`) } return `${query.join('&')}` }else{ return '' }}

以上是幾個比較簡單的案例, 方便大家入門和理解, 實際工作中場景會更復(fù)雜, 但是掌握了基本聲明和定義模式, 基本可以解決大部分ts聲明問題. 作為一名前端工程師, typescript的意義很大,雖然它增加了編程的復(fù)雜度和學(xué)習(xí)成本, 但是長遠(yuǎn)來說, 對于團隊的編碼規(guī)范, 問題定位, 項目維護和代碼管理的角度確實有不少積極作用, 所以學(xué)習(xí)typescript刻不容緩.

最后

如果想學(xué)習(xí)更多H5游戲, webpack,node,gulpcss3,javascript,nodeJS,canvas數(shù)據(jù)可視化等前端知識和實戰(zhàn),歡迎在《趣談前端》專欄學(xué)習(xí)討論,共同探索前端的邊界。

版權(quán)聲明:本文內(nèi)容由互聯(lián)網(wǎng)用戶自發(fā)貢獻,該文觀點僅代表作者本人。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如發(fā)現(xiàn)本站有涉嫌抄襲侵權(quán)/違法違規(guī)的內(nèi)容, 請發(fā)送郵件至 舉報,一經(jīng)查實,本站將立刻刪除。

(0)
上一篇 2023年4月25日 上午9:55
下一篇 2023年4月25日 上午10:11

相關(guān)推薦