Управляемое чтение
Автор имеет более 3 лет практического опыта работы с React + TS и глубоко понимает влияние TS на эффективность производства. Недавно перешел в новую команду, стек технологий Vue3 + TS, это еще шельф, и до глубокого применения еще далеко. Таким образом, передовая практика Vue3 + TS является направлением недавнего исследования автора Теперь поэтапные результаты обобщены в документе для вашего ознакомления.
Примечание: демо-сцена и часть кода из этой статьи будут повторно использованы в другой статье автора.Насколько похожи Vue 3 и React 16.8?Содержание файла , будет объяснено ниже,Не вызывает слишком больших дополнительных затрат на чтение.
задний план
На самом деле, когда Vue 3.2 был выпущен, Youda уже предоставил передовое решение на Weibo:
+ TS + Volar = действительно ароматный
VolarЭто подключаемый модуль VS Code, лично я считаю, что его самая большая роль заключается в решении проблемы подсказки шаблона TS.Уведомление, при его использовании сначалаУдалитьVetur, чтобы избежать конфликтов.
<script setup>используется в однофайловом компоненте (SFC)API композицииСинтаксический сахар времени компиляции для . по сравнению с обычным<script>синтаксис, который имеет больше преимуществ:
- Меньше шаблонов, более чистый код.
- Возможность объявлять свойства и генерировать события, используя чистый Typescript.
- Лучшая производительность во время выполнения (его шаблоны компилируются в функции рендеринга в той же области, без каких-либо промежуточных прокси).
- Лучшая производительность вывода типов IDE (уменьшает работу языковых серверов по извлечению типов из кода).
Подробности смотрите в официальной документацииКомпонент одного файла
Фактически, вышеупомянутый контент в основном решил большинство требований, но все еще есть некоторые потребности, которые не были удовлетворены, в основном 2 пункта.
Один в настоящее времяdefinePropsИспользование типов ТС, импортированных из других файлов, пока не поддерживается.Исходный текст официального сайта:
Сложные типы и импорт типов из других файлов пока не поддерживаются. Теоретически в будущем можно реализовать импорт типов.
Нам необходимо предоставить единое эталонное решение для практического развития.
Во-вторых, лучшая практика режима JSX не дается. Хотя существует не так много сценариев, в которых необходимо использовать JSX для полного использования TS после того, как базовое решение будет готово, он все же является лучшим. Для того, чтобы сделать тему более целенаправленной, в этой статье мы лишь кратко расскажем об идеях, а подробности будут в другой статье.
В дополнение к вышеупомянутым двум пунктам, хотя Ю Да дал направление наилучшей практики, если вы хотите направлять практику команды, вам нужно добавить некоторые детали, особенно случай. Эта статья будет расширять три вышеуказанных пункта соответственно.
Цель
Сначала определите, чего пытается достичь лучшая практика:
- TS дружественный в любом сценарииПодсказки по коду и автодополнение
- Передается при использовании компонентаПодсказки контрольной суммы для реквизита. Такие как
<input :value="value" />Компонент, который может проверить, имеет ли значение строковый тип. - Поток ТС постоянно меняется. Например, синтаксис шаблона Vue также должен успешно выполнять различные функции TS.
Лучшие практики
Дополнительные сведения
Мы по-прежнему используем сцену формы в качестве примера, чтобы сэкономить место, пожалуйста, переместитеНасколько похожи Vue 3 и React 16.8?Контекст см. в разделах «Описание сценария» и «API и типы». Кроме того, в этом подразделе используется только пример формы, чтобы быть достаточно репрезентативным.
Demo - Form
<template>
<div>
<div>
<div>Name</div>
<input type="text" v-model="name" />
</div>
<div>
<div>Sex</div>
<input type="radio" name="sex" :checked="sex === Sex.male" @click="() => sex = Sex.male" />Male
<input type="radio" name="sex" :checked="sex === Sex.female" @click="() => sex = Sex.female" />Female
</div>
<p>
<button @click="handleSubmit">Submit</button>
</p>
</div>
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { Sex, fetchUserInfo, updateUserInfo } from "../services";
const name = ref("");
const sex = ref(Sex.male);
onMounted(() => {
fetchUserInfo("id-xxx").then((res) => {
name.value = res.name;
sex.value = res.sex;
});
});
const handleSubmit = () => {
const params = { name: name.value, sex: sex.value };
updateUserInfo(params).then((res) => {
if (res) alert(JSON.stringify(params));
});
};
</script>
Вышеупомянутая реализация имеет несколько очевидных улучшений по сравнению с обычной реализацией установки + шаблона.
- Длинные возвращаемые значения избегаются, что приводит к значительно меньшему количеству кода. Фактически,
когда используешь
<script setup>когда , любой<script setup>Привязки на верхнем уровне объявления (включая объявления переменных, функций и содержимое, импортированное импортом) можно использовать непосредственно в шаблоне —Официальная документация Vue3
То есть больше нет необходимости объявлять компоненты. Это еще больше сокращает код.
- Кстати, импортированный тип перечисления TS (Sex) также можно легко использовать в шаблоне.
- Если установлен Volar, подсказки по коду и проверка для пола в шаблоне тоже очень удобны.
Видно, что перед лицом обычных сцен,<script setup>Опыт разработки был значительно улучшен. Следующим шагом является дополнение двух других пунктов, упомянутых выше.
defineProps не может импортировать TS извне
Чтобы смоделировать сценарий реквизита, давайте преобразуем случай таблицы:userListбольше не получается из API,но передан через реквизит, посмотрите на код.
Примечание: логика получения данных из API размещена в родительском компоненте TableWrapper, а его код будет размещен в конце текста, чтобы не влиять на ритм текста.
<template>
<table :cellPadding="5" :cellSpacing="5">
<tr>
<th>Name</th>
<th>Sex</th>
</tr>
<tr v-if="userList.length === 0">
No Data
</tr>
<tr v-else v-for="user in userList" :key="user.name">
<td>{{ user.name }}</td>
<td>{{ user.sex === Sex.male ? "Male" : "Female" }}</td>
</tr>
</table>
</template>
<script setup lang="ts">
import { defineProps, withDefaults } from "vue";
import { Sex, UserInfo } from "../services";
interface Props {
userList: UserInfo[];
}
withDefaults(defineProps<Props>(), {
userList: () => [],
});
</script>
Сначала поговорим о самом важном: в официальном документе на сайте говорится, что «импорт из других файлов не поддерживается» означает, чтоdefinePropsПолученный дженерик указан вышеProps. Но, как видно из примера,Sexа такжеUserInfoимпортируются извне и действительно пригодны для использования. То есть, теоретически, в настоящее время он ограничен толькоМежфайловое повторное использование типов TS для реквизитов на уровне компонентовВот и все (пожалуйста, внимательно поймите это предложение). Если это все, это все еще приемлемо. Во-первых, обычно не так много сценариев повторного использования Props между компонентами, а во-вторых, это можно решить с помощью более детального объявления, подобного приведенному выше примеру, но будет некоторая избыточность.
Вот еще несколько важных моментов:
-
definePropsВы можете использовать как объявления времени выполнения, так и объявления типов (см.официальная документация), но не оба. Чтобы сделать поток TS лучше, рекомендуется использовать приведенный выше пример на практике.объявление типаСпособ. -
withDefaultsИспользуется для объявления значения реквизита по умолчанию, используемого так же, как определение объявления во время выполнения.defaultформат тот же. -
defineEmitsПожалуйста, формат объявления типа TSОбязательно сверьтесь с примерами, приведенными на официальном сайте., если он используется неправильно, редактор выдаст ошибку, и не будет запроса кода для эммитов. Конкретный формат выглядит следующим образом:
// e 为 emit 的名字,第二个参数的 key 可以随意定义
const emit = defineEmits<{
(e: 'change', id: number): void
(e: 'update', value: string): void
}>()
Идеи лучших практик JSX
Как упоминалось выше, с приведенными выше рекомендациями не так много мест для использования JSX. Но JSX все еще имеет свои преимущества (из-за инерционного мышления использования React в течение длительного времени), такие как:
- Более гибкий, может использовать любой синтаксис JS, см.Кейс официального сайта;
- props не нужно преобразовывать между маленьким горбом и "-", что более интуитивно понятно и не увеличивает дополнительную нагрузку на память;
Конечно, кто-то скажет, что у него плохое место, мы пока не будем на этом останавливаться и сосредоточимся на лучших практиках JSX. Фактически, функциональные компоненты лучше всего реализуются с помощью JSX, потому что он просто оставляет функцию. Итак, как реализовать общие компоненты? Пожалуйста, дайте автору сначала подготовиться, а адрес другой статьи будет приложен позже.(Обновлено 2021.09.14:Лучшая практика Vue3 + TSX? несуществующий)
Эпилог
В настоящее время установлены базовые рамки лучших практик Vue3 + TS, и кажется, что эффект все еще очень хороший. В соответствии с реальной ситуацией в команде добавьте некоторые технические характеристики практических деталей, и вы сможете с удовольствием попрактиковаться в проекте.
В чем автор уверен, так это в том, что TS будет все больше и больше использоваться во front-end проектах, потому что он может значительно повысить эффективность и качество разработки. Поэтому использование TS в проекте экономически выгодно как для команд, так и для отдельных лиц. Конечно, мы также должны учитывать стоимость миграции,Если вы хотите использовать TS, вам необходимо перейти на Vue3.. Если вы заставите Vue2 использовать TS, поверьте мне, вам это не понравится.
Наконец, сказано, что «после использования TypeScript я больше никогда не захочу использовать JavaScript». Во всяком случае, я поверил.
использованная литература
- Разговор о шаблонах Vue и JSX
- Официальная документация Vue3(Настоятельно рекомендуется внимательно прочитать, такие хорошие документы редкость)
Приложение к коду
TableWrapper.vue
<template>
<Table :user-list="userList" />
</template>
<script setup lang="ts">
import { onMounted, ref } from "vue";
import { fetchUserList, UserInfo } from "../services";
import Table from "./Table.vue";
const userList = ref<UserInfo[]>([]);
onMounted(() => {
fetchUserList().then((res) => {
userList.value = res;
});
});
</script>