使用Vite创建React + TypeScript(node版本为16.17.0,含资源下载)

PC端

安装指令:
npm create vite@latest react-ts-pro -- --template react-ts



Vite是一个框架无关的前端工具链,可以快速的生成一个React + TS的开发环境,并且可以提供快速的开发体验

说明:
1. npm create vite@latest固定写法(使用最新版本vite初始化项目)
2. react-ts-pro  项目名称(自定义)
3. -- --template react-ts   指定项目模板为react+ts

移动端(mobile)

1. 安装:
npm create vite@latest react-jike-mobile -- --template react-ts

2. 安装Ant Design Mobile
npm i --save antd-mobile

初始化路由(react-router-dom, 使用与我另一篇文章一模一样直接参考即可,ReactRouter使用详解(react-router-dom)

1. 安装
npm i react-router-dom

配置路径别名@(使用CRA可参考:cra(create-react-app)配置别名路径@ 以及Vscode联想路径配置

1. 安装插件:
npm i @types/node -D


2. 修改vite.config.ts

import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// 配置别名路径,安装插件后才有path
import path from 'path'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
    
  // 配置别名路径
  resolve: {
    alias: {
      '@': path.resolve(__dirname, './src')
    }
  }
})


3. 修改tsconfig.json

{
  "compilerOptions": {
    // vscode联想配置
    "baseUrl": "./",
    "paths": {
      "@/*": [
          "src/*"
      ]
    }
  }
}

安装插件axios

npm i axios

http.ts封装代码如下:

// 封装axios

import axios from 'axios';

const httpInstance = axios.create({
    baseURL: 'http://geek.itheima.net',
    timeout: 5000
});


// 拦截器
httpInstance.interceptors.request.use(
    config => {
        return config
    },
    error => {
        return Promise.reject(error)
    }
)


httpInstance.interceptors.response.use(
    response => {
        return response
    },
    error => {
        return Promise.reject(error)
    }
)

export default httpInstance;

封装API模块-axios和ts的配合使用

场景:axios提供了request泛型方法,方便我们传入类型参数推导出接口返回值的类型
说明:泛型参数Type的类型决定了res.data的类型


具体演示代码如下:

import { http } from '@/utils';

// 假设后端返回的类型结构是这个
// {
//     data: {
//         channels: [
//             {
//                 id: 1,
//                 name: ''
//             }
//         ]
//     },
//     nessage: ""
// }

/**
 * channel列表查询
 */

// 1. 定义通用泛型(根据后端接口返回的数据来定义)
// data不是写死的,因此用通用的T(T代表泛型)
export type ResType<T> = {
    message: string
    data: T
}



// 2. 子项,定义具体特有的接口类型
type ChannelItem = {
    id: number
    name: string
}

// 整体类型:ChannelRes是data特有的类型
type ChannelRes = {
    channels: ChannelItem[]
}

// 请求频道列表
export function fetchChannelAPI() {
    http.request<ResType<ChannelRes>>({
        url: '/channels'
    })
}

/**
 * 文章列表查询
 */

type ListItem = {
    is_top: string,
    cover: {
        type: number
        image: string[]
    }
}

type ListRes = {
    results: ListItem[]
    pre_timestamp: string
}

// 传参类型
type ReqParams = {
    channel_id: string
    timestamp: string
}

export function fetchListAPI(params: ReqParams) {
    return http.request<ResType<ListRes>>({
        url: '/articles',
        params
    })
}





组件内使用代码如下:

方案一:
fetchChannelAPI().then(res => {
  console.log(res.data)
})

方案二(建议写法):
useEffect(() => {
    const getLists = async () => {
        try {
            const res = await fetchListAPI();
            setLists(res.data);
        } catch (error) {
            throw new Error('fetch channel error')
        }
    }

    getLists();
}, [])

ts基础数据渲染写法

import { useEffect, useState } from 'react';
import { fetchChannelAPI, ChannelItem } from '@/apis/user';

type ChannelItem = {
    id: number
    name: string
}

function Home() {
  const [channels, setChannels] = useState<ChannelItem[]>([]);

  useEffect(() => {
    // const getChannels = async() => {
    //   try {
    //     const res = await fetchChannelAPI();
    //     setChannels(res.data);
    //   } catch (error) {
    //     throw new Error('fetch channel error')
    //   }
    // }

    // getChannels();
  }, [])

  return (
    <div>
      Home
    </div>
  )
}

export default Home;

ts基础数据渲染写法(自定义hook优化)

1. index.tsx代码如下:

import { useTabs } from './useTabs';

function Home() {
  const {channels} = useTabs();

  return (
    <div>
      Home
      <ul>
        {channels.map(item => <li key={item.id}>{item.name}</li>)}
      </ul>
    </div>
  )
}

export default Home;


// 抽离出业务部分封装成useTab
2. useTabs.tsx代码如下:

import { useEffect, useState } from 'react';
import { fetchChannelAPI, ChannelItem } from '@/apis/user';

function useTabs() {
    const [channels, setChannels] = useState<ChannelItem[]>([]);

    useEffect(() => {
        const getChannels = async () => {
            try {
                const res = await fetchChannelAPI();
                setChannels(res.data);
            } catch (error) {
                throw new Error('fetch channel error')
            }
        }

        getChannels();
    }, [])

    return {
        channels
    }
}

export { useTabs };

详情模块 - 路由跳转

1. Home组件代码如下:

// import { useTabs } from './useTabs';

import { useNavigate } from "react-router-dom";

function Home() {
  // const {channels} = useTabs();

  const navigate = useNavigate();
  const goDetail = () => {
    navigate('/detail?id=159')
  }

  return (
    <div>
      Home
      {/* <ul>
        {channels.map(item => <li key={item.id}>{item.name}</li>)}
      </ul> */}
      <hr />
      <button onClick={goDetail}>Detail</button>
    </div>
  )
}

export default Home;



2. Detail组件代码如下:

import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";

function Detail() {
  const [params] = useSearchParams();

  useEffect(() => {
    const id = params.get('id');
    console.log(id);
  }, [])
  return (
    <div>
      Detail
    </div>
  )
}

export default Detail;
相关推荐
Web阿成2 小时前
3.学习webpack配置 尝试打包ts文件
前端·学习·webpack·typescript
wakangda10 小时前
React Native 集成原生Android功能
javascript·react native·react.js
j喬乔12 小时前
Node导入不了命名函数?记一次Bug的探索
typescript·node.js
秃头女孩y16 小时前
【React中最优雅的异步请求】
javascript·vue.js·react.js
前端小小王1 天前
React Hooks
前端·javascript·react.js
迷途小码农零零发1 天前
react中使用ResizeObserver来观察元素的size变化
前端·javascript·react.js
yg_小小程序员1 天前
vue3中使用vuedraggable实现拖拽
typescript·vue
高山我梦口香糖1 天前
[react 3种方法] 获取ant组件ref用ts如何定义?
typescript·react
不是鱼1 天前
构建React基础及理解与Vue的区别
前端·vue.js·react.js
prall1 天前
实战小技巧:下划线转驼峰篇
前端·typescript