задний план
Прошло более полугода с тех пор, как вы выпустили vue3.0 в прошлом году. Не так давно высокопроизводительный You Da выпустил vite2.0, из-за которого я весь день беспокоился о программе для переноса кода, поэтому я хотел изучить и узнать о vue3 и узнать, какие изменения были сделаны по сравнению с vue2.0, и были добавлены новые дополнения, какие особенности. Сначала я прочитал руководство по миграции vue2.0 в целом, а затем начал исследование и обучение с создания простейшего todo mvc.
Создать проект
Я напрямую использовал структуру vite, предоставленную в документе по миграции, для создания проекта, и теперь все больше и больше разработчиков переходят на машинописный текст, поэтому я решил разрабатывать на основе машинописного текста.
определить маршруты
писать маршруты
Домашняя страница используется для отображения списка задач. Щелкните элемент списка, чтобы перейти на страницу сведений, чтобы отобразить сведения о задачах. Создайте новый каталог маршрутизатора следующим образом:
router
├─index.ts
В vue-router4.0 предусмотрено два способа создания истории, а именноcreateWebHistory
а такжеcreateWebHashHistory
. Из-за использования машинописного кодирования при определении константы маршрутов вам необходимо объявить тип какArray<RouteRecordRaw>
.
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
import { defineAsyncComponent } from 'vue'
const routes: Array<RouteRecordRaw> = [
{
path: '/',
redirect: '/home'
},
{
path: '/home',
name: 'home',
component: defineAsyncComponent(() => import('../pages/home.vue'))
},
{
path: '/detail',
name: 'detail',
component: defineAsyncComponent({
loader: () => import('../pages/detail.vue'),
delay: 200,
timeout: 3000
})
}
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
В Vue3.0, черезdefineAsyncComponent
Маршрутизация приложений
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
О настройке
В vue2.0 при написании кода компонента он основан на API опций, черезdata
,watch
,computed
,methods
и другие различные варианты организации логики кода. Однако, когда компонент становится очень большим,логические проблемыСписок будет расти, что приведет к фрагментации логики.Например, когда мы фокусируемся на одной логической точке, мы будем часто переходить к различным блокам опций кода, что затрудняет чтение и понимание логики кода.
Поэтому в vue3.0 появился составной API. Его основная идея состоит в том, чтобы объединить код с одной и той же логической задачей, чтобы иметь возможность его использовать, вы должны предоставить место для его использования, поэтому появляется функция настройки.
Функция настройки выполняется перед созданием компонента и может принимать параметр props и параметр контекста. Как только реквизиты разрешены, они служат точкой входа в составной API.
Поскольку экземпляр компонента не был создан при выполнении установки, его нельзя использовать, поэтому доступ к свойствам, объявленным в компоненте, возможен только через свойства.
Поскольку функция настройки создана вокруг BeForecreate и функция управления крючком, поэтому в Vue3.0 в этих двух функциях не нужно, любой код, написанный в этих двух функциях, должен быть размещен непосредственно в функцию настройки.
Создание компонентов
Создайте новую папку pages в каталоге src и создайте под ней новую папкуhome.vue
а такжеdetail.vue
.
pages
├─home.vue
├─detail.vue
Напишите домашний компонент
Для todomvc элемент todo содержит как минимум два свойства — todo и state, поэтому определите интерфейс Todo:
interface Todo {
text: string,
done: boolean
}
Затем вы можете определить тип тодолиста, который является сложным типом данных. В Vue 3.0, если вы хотите определить основной тип данных в качестве ответа, вам необходимо использовать Ref; если вы хотите определить сложные типы данных в качестве ответа, вам необходимо использовать реактивный, поэтому используйте реактивный характер для определения типа массива объекта :
import { defineComponent, ref, reactive } from 'vue'
export default defineComponent({
setup (props, context) {
let todoList = reactive<Array<Todo>>([
{
text: 'learn js',
done: true
},
{
text: 'learn java',
done: false
}
])
}
})
Поскольку вам нужно динамически добавлять элементы списка дел, вам нужно определить другой строковый тип данных для получения пользовательского ввода:
let inputText = ref('')
Ограничения типа могут быть добавлены здесь без явного указания, потому что typescript автоматически выведет тип как строку на основе параметров, полученных ref.
Todomvc неотделим от добавления и удаления, поэтому мы определяем два метода: addTodo и removeTodo.
const addTodo = () => {
// 记住这里是 `inputText.value`,这是因为基本数据类型被包装成了一个响应式对象,此时只能通过 value 属性来使用它的值
if (inputText.value.trim().length) {
const item = {
text: inputText.value,
done: false
}
todoList.push(item)
inputText.value = ''
}
}
const removeTodo = (index: number) => {
todoList.splice(index, 1)
}
Последний важный шаг - вернуть данные и методы, которые мы определены ранее в функции настройки, поскольку они используются, когда шаблон отображается:
setup (props, context) {
// 此处省略...
return {
todoList,
inputText,
addTodo,
removeTodo
}
}
Подготовка компонентов детали
Детальный компонент очень прост, ему нужно только отобразить объект задачи, переданный при переходе маршрута, включая задачу и статус. Но перед прыжком нужноhome.vue
Определяет способ перехода по маршруту.
Используйте Vue-маршрутизатор 4.0
vue-router4.0 предоставляет новый метод использования, то есть при использовании маршрутизатора или маршрута нам нужно самим импортировать предоставленныеuseRouter
а такжеuseRoute
функция.为了使用 router 进行路由跳转,需要手动 import。
// home.vue
import { useRouter, RouteLocationOptions } from 'vue-router'
export default defineComponent({
setup (props, context) {
let router = useRouter()
// ...
const jumpToDetail = (item: Todo) => {
router.push({
name: 'detail',
params: {
text: item.text,
done: item.done
}
} as RouteLocationOptions)
}
return {
todoList,
inputText,
addTodo,
removeTodo,
jumpToDetail,
router
}
}
})
Следует отметить, что наш маршрутный переход выполнен в виде объекта push, поэтому нам нужно указать, что этот объект имеет тип RouteLocationOptions, который предоставляется vue-router. Если push является строкой, вам нужно указать тип строки как RouteLocationRaw.
Получить параметры маршрута
Как упоминалось выше, в vue-router4.0, если вы хотите получить объект маршрута, вам нужно использовать useRoute, поэтому вам нужно импортировать вручную.
<template>
<div id="detail">
<h2>将来要做什么: {{ todo.text }}</h2>
<h2>状态:<input type="checkbox" v-model="checked"/>{{ todo.done ? '已完成' : '未完成' }}</h2>
</div>
</template>
import { useRoute } from 'vue-router'
import { ref, reactive, watch, defineComponent } from 'vue'
export default defineComponent({
name: 'detail',
setup (props, context) {
const route = useRoute()
// 使用 params,刷新页面参数会丢失
const done = route.params.done === 'true' ? true : false
let todo = reactive({
text: route.params.text,
done
})
let checked = ref(todo.done)
watch(checked, (newV, oldV) => {
if (newV) {
todo.done = true
} else {
todo.done = false
}
}, {
deep: true
})
return {
todo,
route,
checked
}
}
})
Здесь нужно использовать функцию наблюдения, чтобы, когда мы ставим галочку, состояние можно было вовремя изменить. В отличие от опции watch в vue2.0, watch в vue3.0 — это чистая функция, которую можно использовать несколько раз.В число получаемых параметров входят: цель прослушивания, функция обратного вызова и дополнительные параметры, а третий параметр получает объект. содержит варианты глубокого прослушивания и немедленного исполнения.
О getCurrentInstance для получения текущего экземпляра компонента
В vue2 после того, как мы создадим корневой экземпляр и смонтируем маршрутизатор, мы можем передать его в любой компонент позже.this.$router.xxx
использовать маршрутизацию. Но в Vue3, поскольку функция установки работает вокруг BeForecreate и создает крючки, экземпляр компонента не может быть получен через это. Рекомендуемая практика является импортvue-router
изuseRouter
а такжеuseRoute
Перейти к маршруту означает получить параметры, переданные маршрутом.
Но в vue3 при условииgetCurrentInstance
Функция, как следует из названия, функцией этой функции является получение текущего экземпляра компонента. Затем я вызываю функцию и печатаю текущий экземпляр:
Нажмите, чтобы просмотреть сведения о CTX:
vue2
ctx.$router.xxx
использовать маршрутизацию, поэтому я попробовал следующее:
const { ctx } = getCurrentInstance()
console.log('current instance:', ins)
Но typescript сразу выводит ошибку типа:
Здесь ctx будет типом объединения, либоComponentInternalInstance
тип, который также может бытьnull
Типы. мы можем видетьComponentInternalInstance
Какие типы объявлены в интерфейсе:
Это очень странно, почему я могуgetCurrentInstance
как насчет ктх? Выяснилось, что vite по умолчанию использует среду разработки, что удобно для получения инстанса на этапе разработки, поэтому я переключился на среду разработки:
Я вижу, что в ctx ничего нет.