портал
- первая серия практических проектов vite + react + ts (конфигурация проекта)
- адрес github (github обновляется быстрее, чем документ, и к документу нужно добавить много комментариев)гитхаб-адрес
предисловие
-
Эта актуальная боевая статья, которую я много раз переделывал, изначально добавлял много сложных пакетов, но она очень недружелюбна для студентов-новичков в react+ts, потому что ее нелегко понять Поэтому я сокращаю, сокращаю и сокращаю, стараюсь писать так, чтобы все могли понять, стараюсь использовать краткий язык, чтобы выразить, какие функции мы хотим сделать, сначала легко, а затем сложно.
-
Инкапсуляция сложных функций будет подробно объяснена в следующей серии статей, пошаговое углубленное изучение, Большая часть кода в проекте снабжена подробными комментариями, надеюсь, вы не запутаетесь, потому что когда я был новичком, я искал опенсорсные проекты на github, их много Проект хорошо упакован, но Xiaobai очень запутался и должен долго смотреть его, поэтому я постараюсь подробно объяснить в этом уроке.Согласно документации, проект может выполняться, а аннотации подробно написано, а затем сотрудничайте с прямой трансляцией, чтобы рассказать о ней.
-
ts Не думайте, что это сложно, зайдите на официальный сайт, чтобы увидеть основные способы использования, вы можете это сделать, просто проверьте грамматику, которую вы не понимаете, просто используйте ее несколько раз.
-
То же самое верно и для реакции, не будьте невежественны и нуждайтесь в большой практике кода. Если не понимаете, спросите, а если не знаете, проверьте.
-
В этой статье в основном пишут
-
Использование поддельных данных json-сервера
-
Простое использование интерфейса запроса
-
Простое использование маршрутизации
-
Некоторые простые данные глобальной конфигурации
-
международное использование
-
Инкапсуляция простых общих компонентов
-
фиктивные данные json-сервера
-
yarn add json-server -D
-
в терминале
mkdir mock cd mock touch db.json
-
Добавьте скрипты в package.json
"mock": "json-server mock/db.json --port 3008"
-
Затем запустите команду yarn mock, чтобы успешно получить доступ к данным интерфейса, которые мы настроили в db.json в консоли.
инкапсуляция запроса
Примечание: process.env следует заменить на import.meta.env.
- Глобальные общедоступные файлы конфигурации будут размещены в файле config.ts в корневом каталоге.В настоящее время в начале проекта имеется лишь небольшой объем информации о конфигурации.
/**
* 当前环境变量
*/
// process.env 在vite中不能用
// export const whyEnv = import.meta.env.VITE_REACT_URL || "";
/**
* 接口地址
* @description env 可为主要环境或自定义地址
*/
export const apiAddress = "http://localhost:3008/";
/**
* 开发代理前缀
*/
export const proxyApi = "/api";
/**
* 接口前缀
* 判断环境,是否需要使用前缀
* 生产环境不需要代理,同时本地配置的代理在生产环境也是不能用的
*/
export const urlPrefix = process.env.NODE_ENV === "development" ? proxyApi : "";
- Библиотека umi-request, используемая в проекте, на данный момент я настроил очень мало вещей, таких как обработка ошибок, обработка промежуточного ПО и т. д. Я ее удалил, не стал так усложнять в начале.
// utils/request.ts
/**
* request 网络请求工具
* 更详细的 api 文档: https://github.com/umijs/umi-request
*/
import umiRequest, { extend } from "umi-request";
import { urlPrefix } from "../config";
// 使用前缀,配合本地代理
export const whyRequest = extend({
prefix: `${urlPrefix}`,
});
export default umiRequest;
- Определите интерфейс: необходимо заранее сообщить входные параметры и формат выходных параметров с последним разделом.В сочетании с подсказкой типа ts вы можете напрямую видеть свойства, определенные интерфейсом, при вызове в других местах, что очень удобно.
/**
* 登陆请求数据类型
*/
export interface ILogin {
userName: string;
pwd: string;
}
/**
* 返回数据类型
* 要提前和后段定义好类型,等接口写完直接替换地址就好了
*
*/
export interface ILoginData {
code: number;
message: string;
token: string;
}
/**
* 登陆接口
* @param params
*/
export const loginApp = (params: ILogin): Promise<ILoginData> => {
return whyRequest.get("/login", params);
};
- Он очень прост в использовании, вызовите его напрямую, а затем мы будем сотрудничать с useRequest() в ahooks.
loginApp({ userName: "why", pwd: "123" }).then((res) => {
if (res.code === 200) {
history.push("/home");
} else {
message.error("用户名或密码错误!");
}
});
международная конфигурация
- yarn add react-intl -D
- Для интернационализации мы используем react-intl, а также совместимы с китайским и английским языками antd и другими плагинами.Когда мы переключаем языки, библиотека плагинов также должна быть напрямую переключена на соответствующий язык, что также очень удобно. удобно настроить.
- переходим непосредственно к коду
// 引入创建语言,国际化容器,暂时我们只需要用这两个就可以实现的我们目前的功能
import { createIntl, IntlProvider } from "react-intl";
// 我们需要引入antd 的国际化的配置
import antdEnUS from "antd/lib/locale/en_US";
import antdZhCN from "antd/lib/locale/zh_CN";
// 这是我们项目中中英文的配置,
import enLn from "./components/ln-en";
import zhLn from "./components/ln-zh-cn";
···核心代码
/**
* 包裹了默认 locale 的 Provider
* LocaleProvider 需要在App.tx使用,包装整个项目
* @param props
* @returns
*/
export const LocaleProvider: React.FC = (props) => {
return <IntlProvider locale={getLocale()}>{props.children}</IntlProvider>;
};
/**
* 获取当前的 intl 对象,可以在 node 中使用
* @param locale 需要切换的语言类型
* @param changeIntl 是否不使用 g_intl
* @returns IntlShape
*/
const getIntl = (locale?: string, changeIntl?: boolean) => {
// 如果全局的 g_intl 存在,且不是 setIntl 调用
if (gIntl && !changeIntl && !locale) {
return gIntl;
}
// 如果存在于 localeInfo 中
if (locale && localeInfo[locale]) {
return createIntl(localeInfo[locale]);
}
// 使用默认语言
if (localeInfo[defaultLanguage])
return createIntl(localeInfo[defaultLanguage]);
// 使用 zh-CN
if (localeInfo["zh-cn"]) return createIntl(localeInfo["zh-cn"]);
// 抛错
if (!locale || !!localeInfo[locale]) {
throw new Error(
"The current popular language does not exist, please check the locales folder!"
);
}
// 如果还没有,返回一个空的
return createIntl({
locale: "zh-cn",
messages: {},
});
};
/**
* 语言转换
* @param descriptor
* @param values
*/
export const formatMessage = (
descriptor: MessageDescriptor,
values?: Record<string, any>
) => {
if (!gIntl) {
setIntl(getLocale());
}
return gIntl.formatMessage(descriptor, values);
};
-
используется на странице
1. Нам нужно настроить контрастность китайского и английского языков в соответствующем файле ts.
// 在locale 文件下配置中文对照 export default { frontEnd: "Work hard on the front end", switchLan: "Chinese-English shift", switchToEn: "switch to chinese", switchToCh: " switch to english", localLan: "The internationalization of this project is based on", }; // 配置英文对照 export default { frontEnd: "前端要努力", switchLan: "中英文切换", switchToEn: "切换到中文", switchToCh: "切换到英文", localLan: "本项目国际化基于", };
2. На странице мы напрямую вызываем метод formatMessage().
/**
* 国际化页面
* @constructor
*/
const LocalePage: React.FC = () => {
// 这使用的是useState,其实这里是完全不需要的
const [value, setValue] = React.useState(
localStorage.getItem("why__locale") || "zh-cn"
);
// 切换多语言
const onChange = (e: RadioChangeEvent) => {
setValue(e.target.value); //在这里是没有作用的代码
setLocale(e.target.value); // 调用切换多语言方法,然后刷新页面
};
return (
<Card title={formatMessage({ id: "switchLan" })} style={{ width: "500px" }}>
<Radio.Group onChange={onChange} value={value}>
<Radio value={"zh-cn"}>{formatMessage({ id: "switchToEn" })}</Radio>
<Radio value={"en"}>{formatMessage({ id: "switchToCh" })}</Radio>
</Radio.Group>
<div className={styles.localLan}>
{formatMessage({ id: "localLan" })}react-intl
</div>
</Card>
);
};
- Интернационализированные страницы
маршрутизация
-
Система маршрутизации React сильно отличается от Vue. Перед навигацией по маршрутизации нет хука. Чтобы настроить аутентификацию при входе, вы должны настроить ее самостоятельно. В сочетании с токеном,
-
Целью маршрутизации в нашем проекте является поддержка динамической маршрутизации, разрешений маршрутизации и извлечения конфигурации.В настоящее время это самый простой, голый
инкапсуляция общедоступного компонента
-
Как мы инкапсулируем публичный компонент?
1. Компоненты, которые необходимо использовать в нескольких местах проекта.
2. Компоненты, не связанные с бизнесом, публичные компоненты, связанные с бизнесом
3. Всеми состояниями можно управлять извне, а их поведение контролируется входящим реквизитом вместо того, чтобы обнажать его внутреннюю структуру.
封装良好的组件隐藏其内部结构,并提供一组属性来控制其行为。 隐藏内部结构是必要的。其他组件没必要知道或也不依赖组件的内部 结构或实现细节
-
Единый каталог в нашем проекте, в основном для удобства
-
содержание:
-
index.tsx — основной файл записи
-
index.md — это пример использования компонента, необходимые комментарии к коду, и необходимо четко рассказать другим, как использовать этот общий компонент
-
Как использовать значки шрифта iconfont
- Инкапсулируйте значок, в основном сотрудничайте с antd createFromIconfontCN, чтобы напрямую ввести значок шрифта в iconfont, что очень удобно.
- Как показано на рисунке ниже, войдите непосредственно на веб-сайт iconfont, чтобы сгенерировать соответствующий файл js, просто используйте его непосредственно в проекте, это очень просто.
- Использование имен классовПредставляем нпм
// 简单来说
// 这里可以根据各属性动态添加,如果属性值为true则为其添加该类名,
// 如果值为false,则不添加。这样达到了动态添加class的目的
<FontIcon
className={classNames(
{
[styles.large]: size === "large", // 返回为true使用css .large,下方同理
[styles.normal]: size === "normal",
[styles.small]: size === "small",
[styles.disabled]: disabled,
},
className
)}
{...restProps}
/>
- Использование React.FC 1.React.FC — это функциональный компонент, который является универсальным типом, используемым в TypeScript.FC — это аббревиатура от FunctionComponent.На самом деле React.FC можно записать как React.FunctionComponent:
const App: React.FunctionComponent<{ message: string }> = ({ message }) => (
<div>{message}</div>
);
2.React.FC включает общий тип PropsWithChildren без явного объявления типа props.children. React.FC является явным для возвращаемого типа, в то время как обычная версия функции является неявной (в противном случае требуется дополнительный комментарий).
3. React.FC предоставляет статические свойства с проверкой типов и автозаполнением: displayName, propTypes и defaultProps (примечание: у defaultProps будут некоторые проблемы с React.FC).
4. Когда мы используем React.FC для написания компонентов React, мы не можем использовать setState, вместо этого мы используем Hook API, такие как useState() и useEffect.
Инкапсулировать общедоступные компоненты значка
// IconType继承React.HTMLAttributes的属性,然后IconType,就拥有了其可被外界访问的属性
export interface IconType extends React.HTMLAttributes<any> {
// type 必有属性,如果使用的时候没有静态检查是,会提示错误,类型不匹配,使用ts的好处,静态类型检查非常nice
// 报错如下:TS2741: Property 'type' is missing in type '{}' but required in type 'IconType'. index.tsx(7, 3): 'type' is declared here.
type: string;
// 图标尺寸,默认 normal
size?: "small" | "normal" | "large" | null; // 可选属性,size后面加上?
// 是否禁用
disabled?: boolean;
}
// createFromIconfontCN 返回一个组件
const FontIcon = createFromIconfontCN({
// 请给新图标一个合适的驼峰命名,并保证单词正确
scriptUrl: "//at.alicdn.com/t/font_955172_ymhvgyhjk.js",
});
const Icon: React.FC<IconType> = ({
className,
size = "normal",
disabled,
...restProps
}) => {
// 我们使用classNames 这个插件动态渲染icon的状态,size,disabled等等
return (
<FontIcon
className={classNames(
{
[styles.large]: size === "large",
[styles.normal]: size === "normal",
[styles.small]: size === "small",
[styles.disabled]: disabled,
},
className
)}
{...restProps}
/>
);
};
// 思考题:这个地方需要用,react.memo吗?
export default React.memo(Icon);
- Использование (на скриншоте есть общедоступные компоненты iconSelect, в этой статье объяснять не буду)
Эпилог
- первая серия практических проектов vite + react + ts (конфигурация проекта)
- адрес github (github обновляется быстрее, чем документ, и к документу нужно добавить много комментариев)гитхаб-адрес
- Если у вас есть какие-либо вопросы, вы можете подать проблему или добавить блогер: lisawhy0706
-
В следующей статье будут в основном объясняться некоторые сложные компоненты
- Улучшить функционал в проекте
- Обработка общедоступной конфигурации
- Инкапсуляция пользовательских хуков
- Как разработать разрешения для проекта, включая разрешения на маршрутизацию, разрешения на уровне кнопок