предисловие
Vue3.0 был официально выпущен в сентябре прошлого года, и все с энтузиазмом принимают Vue3.0. В начале этого года новые проекты также начали использовать Vue3.0 для разработки.Эта статья представляет собой сводку после использования, включая использование новых функций Vue3 и некоторый обмен опытом.
Зачем переходить на Vue3
Оба друга, использующие Vue2.x, знакомы, все данные в Vue2.x определеныdata
, метод определен вmethods
в и использоватьthis
для вызова соответствующих данных и методов. Во Vue3.x так играть нельзя.О том, как в нее играть, мы поговорим позже.Сначала поговорим о дефектах версии Vue2.x, написанной таким образом, и будут сделаны все апгрейды.
Просмотрите Vue2.x для реализации сложения и вычитания
<template>
<div class="homePage">
<p>count: {{ count }}</p>
<p>倍数: {{ multiple }}</p>
<div>
<button style="margin-right: 10px" @click="increase">加1</button>
<button @click="decrease">减一</button>
</div>
</div>
</template>
<script>
export default {
data() {
return { count: 0 };
},
computed: {
multiple() {
return 2 * this.count;
},
},
methods: {
increase() {
this.count++;
},
decrease() {
this.count--;
},
},
};
</script>
Приведенный выше код просто реализуетcount
Сложение, вычитание и отображение множителей должны выполняться в данных, методах и вычисляться соответственно.Когда мы добавим требование, появится следующий рисунок:
Когда наш бизнес сложный, описанная выше ситуация будет происходить в большом количестве.По мере увеличения сложности будет появляться такая картина.Каждый цветной квадрат представляет собой функцию:
Даже функция будет зависеть от других функций, смешанных вместе.
Когда код этого компонента превышает несколько сотен строк, чтобы добавить или изменить определенное требование, необходимо многократно прыгать в данные, методы, вычислять и монтировать.Все знают, как это больно.
Тогда мы подумали, что если мы сможем разделить картинку выше на картинку ниже, она будет намного понятнее, если мы сможем разделить ее логически, такой код будет более читаемым и удобным для сопровождения:
Тогда решение, данное версией vue2.x, — это Mixin, но использование Mixin также столкнется с раздражающими проблемами:
- Проблема конфликта имен
- Непонятно, что делают открытые переменные.
- Повторное использование логики для других компонентов часто вызывает проблемы
Я не буду приводить примеры вышеперечисленных часто встречающихся проблем, и знакомые, которые ими пользовались, в той или иной степени столкнутся с ними. В центре внимания статьи не Mixin, если вы действительно хотите знать, просто оставьте сообщение~
Итак, мы запустили Vue3.xComposition API
Основная цель — решить вышеперечисленные проблемы, объединить разбросанную и распределенную логику вместе для обслуживания, а также может разбить отдельную функциональную логику на отдельные файлы. Далее мы сосредоточимся наComposition API
.
Composition API
setup
setup — это новая опция в Vue3.x, которая используется в компонентахComposition API
Вход.
Время выполнения установки
Я видел много статей в процессе изучения того, что установка находится вbeforeCreate
а такжеcreated
Между тем этот вывод неверен. Практика — единственный критерий проверки истины, поэтому я проверил это на себе:
export default defineComponent({
beforeCreate() {
console.log("----beforeCreate----");
},
created() {
console.log("----created----");
},
setup() {
console.log("----setup----");
},
});
Время выполнения установки — до beforeCreate. Подробности см. в описании жизненного цикла позже.
параметр настройки
использоватьsetup
, он принимает два параметра:
- props: свойства, переданные компонентом
- context
принято в настройкахprops
Он реактивный и будет обновляться вовремя, когда будут переданы новые реквизиты. Так как он отзывчивый, поэтомуНе могу использовать деструктурирование ES6, деструктуризация лишает его отзывчивости.Пример кода ошибки, этот код заставит props больше не поддерживать реактивность:
// demo.vue
export default defineComponent ({
setup(props, context) {
const { name } = props
console.log(name)
},
})
что в развитии мыЕсли вы хотите использовать деструктурирование, вы все равно можете оставитьprops
отзывчивый, есть ли способ решить это? Вы можете подумать об этом, в спинуtoRefs
Место, чтобы узнать ответы для всех.
Далее поговорим оsetup
Принятый второй параметрcontext
, мы сказали ранееsetup
Наиболее часто используемые в Vue2 недоступны вthis
объект, поэтомуcontext
предоставлено вthis
Три наиболее часто используемых свойства:attrs
,slot
а такжеemit
, соответствующий Vue2.x соответственно$attr
Атрибуты,slot
слот и$emit
событие запуска. И эти свойства автоматически синхронизируются с последними значениями, поэтому мы получаем самые последние значения каждый раз, когда их используем.
реактивный, ref и toRefs
В vue2.x данные определения находятся вdata
, Но его можно использовать vue3.xreactive
а такжеref
для определения данных.
Такref
а такжеreactive
В чем разница между ними? Когда они используются? Сказав это, я должен упомянуть, что я видел много статей в Интернете, в которых говорилось, что (reactive
Двусторонняя привязка для работы с объектами,ref
затем обрабатывает двустороннюю привязку базовых типов js). Я на самом деле не согласен с таким утверждением, новичкам легко подумать, чтоref
может обрабатывать основные типы js, такие какref
Также возможно определить двустороннюю привязку объектов, приведенный выше код:
setup() {
const obj = ref({count:1, name:"张三"})
setTimeout(() =>{
obj.value.count = obj.value.count + 1
obj.value.name = "李四"
}, 1000)
return{
obj
}
}
мы будемobj.count
а такжеobj.name
Привязка к странице тоже возможна, однакоreactive
Функции действительно могут проксировать объект, но не примитивные типы, такие как строки, числа, логические значения и т. д.
Затем используйте код, чтобы показатьref
,reactive
использование:текущий результат:В приведенном выше коде мы привязываемся к странице черезuser.name
,user.age
; Кажется, очень громоздко писать так, можем ли мы напрямуюuser
Как насчет деконструкции свойств вuser
Структурируйте его так, чтобы он был отзывчивым, здесь и выше мы сказалиprops
Вы не можете использовать ES6 для прямой деконструкции. Тогда что, если мы хотим использовать деструктурированные данные, решение таково:использоватьtoRefs
.
toRefs используется для преобразования реактивного объекта в обычный объект, все свойства которого являются объектами ref. Конкретное использование заключается в следующем:
<template>
<div class="homePage">
<p>第 {{ year }} 年</p>
<p>姓名: {{ nickname }}</p>
<p>年龄: {{ age }}</p>
</div>
</template>
<script>
import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
setup() {
const year = ref(0);
const user = reactive({ nickname: "xiaofan", age: 26, gender: "女" });
setInterval(() => {
year.value++;
user.age++;
}, 1000);
return {
year,
// 使用reRefs
...toRefs(user),
};
},
});
</script>
крючки жизненного цикла
Мы можем прямо посмотреть на диаграмму жизненного цикла, чтобы узнать, какие есть крючки жизненного цикла (картинка нарисована согласно переводу официального сайта):Из рисунка видно, что Vue3.0 добавилsetup
, мы также подробно описали это ранее, а затем Vue2.xbeforeDestroy
имя изменено наbeforeUnmount
; destroyed
стол большеunmounted
, автор говорит, что это изменение чисто для большей семантики, потому что компонент — этоmount
а такжеunmount
процесс. Другие жизненные циклы в Vue2 все еще сохраняются.
верх生命周期图
Он не содержит всех хуков жизненного цикла, есть несколько других, все хуки жизненного цикла показаны на рисунке:Мы видим, чтоbeforeCreate
а такжеcreated
одеялоsetup
Заменено (но вы все еще можете использовать его в Vue3, потому что Vue3 обратно совместим, то есть вы фактически используете vue2). Во-вторых, добавлено имя хука.on
; Vue3.x также добавляет хуки для отладкиonRenderTriggered
а такжеonRenderTricked
Ниже мы просто используем несколько хуков, чтобы вы могли научиться их использовать.Хук в Vue3.x необходимо импортировать из vue:
import { defineComponent, onBeforeMount, onMounted, onBeforeUpdate,onUpdated,
onBeforeUnmount, onUnmounted, onErrorCaptured, onRenderTracked,
onRenderTriggered } from "vue"; export default defineComponent({ //
beforeCreate和created是vue2的 beforeCreate() {
console.log("------beforeCreate-----"); }, created() {
console.log("------created-----"); }, setup() { console.log("------setup-----");
// vue3.x生命周期写在setup中 onBeforeMount(() => {
console.log("------onBeforeMount-----"); }); onMounted(() => {
console.log("------onMounted-----"); }); // 调试哪些数据发生了变化
onRenderTriggered((event) =>{ console.log("------onRenderTriggered-----",event);
}) }, });
Здесь представлен контент, связанный с жизненным циклом, давайте представим Vue3.x.watch
в чем разница.
Использование часов и часового эффекта
Функция наблюдения используется для прослушивания определенного источника данных и выполнения побочных эффектов в функции обратного вызова. По умолчанию используется ленивый, что означает, что обратный вызов выполняется только при изменении исходных данных прослушивания.
watch(source, callback, [options])
Описание параметра:
- источник: может поддерживать строку, объект, функцию, массив; используется для указания адаптивной переменной для прослушивания
- callback: функция обратного вызова для выполнения
- варианты: поддерживает глубокие, немедленные и флеш-опции.
Далее я расскажу, как используются эти три параметра.Если вы не понимаете, как использовать часы, прочитайте ниже:
слушать реактивные определенные данные
import { defineComponent, ref, reactive, toRefs, watch } from "vue";
export default defineComponent({
setup() {
const state = reactive({ nickname: "xiaofan", age: 20 });
setTimeout(() => {
state.age++;
}, 1000);
// 修改age值时会触发 watch的回调
watch(
() => state.age,
(curAge, preAge) => {
console.log("新值:", curAge, "老值:", preAge);
}
);
return {
...toRefs(state),
};
},
});
слушать данные, определенные ссылкой
const year = ref(0);
setTimeout(() => {
year.value++;
}, 1000);
watch(year, (newVal, oldVal) => {
console.log("新值:", newVal, "老值:", oldVal);
});
слушать несколько данных
В приведенных выше двух примерах мы использовали две часы соответственно.Когда нам нужно прослушивать несколько источников данных, мы можем объединить их и одновременно прослушивать несколько данных:
watch([() => state.age, year], ([curAge, newVal], [preAge, oldVal]) => {
console.log("新值:", curAge, "老值:", preAge); console.log("新值:", newVal,
"老值:", oldVal); });
Слушайте сложные вложенные объекты
В нашей реальной разработке сложные данные можно увидеть повсюду, например:
const state = reactive({
room: {
id: 100,
attrs: {
size: "140平方米",
type: "三室两厅",
},
},
});
watch(
() => state.room,
(newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
},
{ deep: true }
);
Если третий параметр не используетсяdeep:true
, не может отслеживать изменения данных.
Ранее мы упоминали,часы ленивы по умолчанию, тогда при каких обстоятельствах не лениво и callback-функцию можно выполнить сразу? На самом деле использование тоже очень простое, задается в третьем параметреimmediate: true
Вот и все. оflush
Конфигурация еще учится, будет добавлена позже
перестань слушать
мы создали в компонентеwatch
Прослушивание автоматически остановится, когда компонент будет уничтожен. Если мы хотим остановить прослушиватель до того, как компонент будет уничтожен, мы можем вызватьwatch()
Возвращаемое значение функции следующее:
const stopWatchRoom = watch(() => state.room, (newType, oldType) => {
console.log("新值:", newType, "老值:", oldType);
}, {deep:true});
setTimeout(()=>{
// 停止监听
stopWatchRoom()
}, 3000)
Также есть функция прослушиванияwatchEffect
, я считаюwatch
Он уже может удовлетворить потребности мониторинга, зачемwatchEffect
Шерстяная ткань? Хотя у меня нет необходимости его получать, я все же хочу представить егоwatchEffect
, сначала посмотрите на его использование иwatch
В чем разница.
import { defineComponent, ref, reactive, toRefs, watchEffect } from "vue";
export default defineComponent({
setup() {
const state = reactive({ nickname: "xiaofan", age: 20 });
let year = ref(0)
setInterval(() =>{
state.age++
year.value++
},1000)
watchEffect(() => {
console.log(state);
console.log(year);
}
);
return {
...toRefs(state)
}
},
});
Результат выполнения сначала печатается один разstate
а такжеyear
значение; затем каждую секунду печататьstate
а такжеyear
стоимость.
Как видно из приведенного выше кода, нетwatch
Также необходимо сначала передать зависимости,watchEffect
Зависимости собираются автоматически, достаточно указать функцию обратного вызова. Когда компонент будет инициализирован, он будет выполнен один раз для сбора зависимостей, а затем, когда данные в собранных зависимостях изменятся, функция обратного вызова будет выполнена снова. Таким образом, общее сравнение выглядит следующим образом:
- watchEffect не нужно вручную передавать зависимости
- watchEffect будет выполняться один раз для автоматического сбора зависимостей
- watchEffect не может получить значение до изменения, только значение после изменения
Vue3 был представлен вышеComposition API
Часть контента, есть много очень полезных API, рекомендуется напрямую проверить состав API официального сайта.
На самом деле, мы также можем сделать индивидуальную упаковку.
Пользовательские крючки
Вначале мы использовали Vue2.x, чтобы написать пример сложения и вычитания, который можно инкапсулировать здесь как хук Мы договорились, что эти «пользовательские хуки» имеют префикс использования, чтобы отличить их от обычных функций.useCount.ts
выполнить:
import { ref, Ref, computed } from "vue";
type CountResultProps = {
count: Ref<number>;
multiple: Ref<number>;
increase: (delta?: number) => void;
decrease: (delta?: number) => void;
};
export default function useCount(initValue = 1): CountResultProps {
const count = ref(initValue);
const increase = (delta?: number): void => {
if (typeof delta !== "undefined") {
count.value += delta;
} else {
count.value += 1;
}
};
const multiple = computed(() => count.value * 2);
const decrease = (delta?: number): void => {
if (typeof delta !== "undefined") {
count.value -= delta;
} else {
count.value -= 1;
}
};
return {
count,
multiple,
increase,
decrease,
};
}
Давайте посмотрим на использование компонентовuseCount
этоhook
:
<template>
<p>count: {{ count }}</p>
<p>倍数: {{ multiple }}</p>
<div>
<button @click="increase()">加1</button>
<button @click="decrease()">减一</button>
</div>
</template>
<script lang="ts">
import useCount from "../hooks/useCount";
setup() {
const { count, multiple, increase, decrease } = useCount(10);
return {
count,
multiple,
increase,
decrease,
};
},
</script>
Открытая реализация Vue2.x, дисперсияdata
,method
,computed
Подождите, если вы только что взялись за проект, вы действительно не можете быстроdata
поля иmethod
На пути Vue3 ясно видно, что гораздо удобнее агрегировать логику, связанную с подсчетом, иuseCount
Дополнительные функции также могут быть расширены.
После того, как проект будет разработан, я напишу статью с кратким изложением «пользовательских хуков», используемых в проекте, чтобы помочь вам в разработке более эффективно.Composition API
Здесь представлены пользовательские хуки, а затем кратко представлено сравнение отзывчивости между vue2.x и vue3.
Простое сравнение отзывчивости vue2.x и vue3.x
На самом деле, когда тема Vue3.x не выпущена, это огонь.Vue3.x 将使用 Proxy 取代 Vue2.x 版本的 Object.defineProperty
.
Нет любви без причины, и нет ненависти без причины. Почему долженObject.defineProperty
Если вы измените его, мы можем кратко рассказать об этом.
При первом запуске Vue2.x часто сталкивался с проблемой, обновлялись данные, почему страница не обновляется? когда использовать$set
обновить, когда$forceUpdate
Вынужден обновить, вы когда-нибудь были в беде. Позже в процессе обучения я начал связываться с исходным кодом, и тогда я понял, что корень всегоObject.defineProperty
.
Для тех, кто хочет узнать больше об этой части, вы можете прочитать эту статью Почему Vue3.0 больше не использует defineProperty для реализации мониторинга данных? Подробно объяснить можно в другой статье, вот простое сравнениеObject.defineProperty
с прокси
-
Object.defineProperty
Вы можете угнать только свойства объекта, а прокси - прямой прокси-объект
из-заObject.defineProperty
Только свойства объекта могут быть захвачены, и каждое свойство объекта необходимо пройти.Если значение свойства также является объектом, требуется рекурсивный глубокий обход. Но прокси напрямую прокси-объект, нет необходимости проходить операцию
-
Object.defineProperty
Добавление свойств необходимо выполнять вручнуюObserve
потому чтоObject.defineProperty
Перехват — это атрибут объекта, поэтому при добавлении нового атрибута вам нужно снова пройтись по объекту и снова использовать новый атрибут.Object.defineProperty
угон. То есть при добавлении свойств к массивам и объектам в Vue2.x нужно использовать$set
Чтобы новые свойства также реагировали,$set
Внутренне также по телефонуObject.defineProperty
иметь дело с.
Teleport
Телепорт — это новая функция Vue3.x, и те, кто не слышал этого слова, могут почувствовать себя незнакомыми;传送
Я все еще могу чувствовать, что не знаю, что это значит, поэтому я дам вам описание изображения ниже.
Что такое Телепорт?
Телепорт похож на «любую дверь» в Дораэмоне, функция любой двери — мгновенно телепортировать людей в другое место. С этим пониманием давайте посмотрим, почему нам нужно использовать возможности Teleport.Давайте рассмотрим небольшой пример:
в подкомпонентеHeader
используется вDialog
компонент, мы часто используем его в подобных ситуациях в реальной разработкеDialog
,В настоящее времяDialog
Он визуализируется в виде слоя подкомпонентов для управления позиционированием вложенных компонентов.z-index
и стили стали трудными.Dialog
С точки зрения восприятия пользователем, это должен быть самостоятельный компонент, а DOM, смонтированный компонентом верхнего уровня Vue, должен быть полностью отделен от структуры dom, при этом также может использоваться состояние в компоненте Vue (data
илиprops
) стоимость. Проще говоря,то есть хотите продолжать использовать внутри компонентаDialog
, и надеемся, что визуализированная структура DOM не вложена в DOM компонента..
На данный момент нам нужен Телепорт для игры, мы можем использовать<Teleport>
пакетDialog
, в этот момент устанавливается портал, который можетDialog
Визуализированный контент доставляется в любое указанное место.
Далее, давайте возьмем небольшой пример, чтобы увидеть, как используется Teleport.
Использование телепорта
Мы надеемся, что Dialog rendering dom и компоненты верхнего уровня являются родственными отношениями, вindex.html
Файл определяет элемент для монтажа:
<body>
<div id="app"></div>
<div id="dialog"></div>
</body>
определитьDialog
компонентыDialog.vue
, обрати внимание наto
свойства такие же, как и вышеid
Селекторы те же:
<template>
<teleport to="#dialog">
<div class="dialog">
<div class="dialog_wrapper">
<div class="dialog_header" v-if="title">
<slot name="header">
<span>{{ title }}</span>
</slot>
</div>
</div>
<div class="dialog_content">
<slot></slot>
</div>
<div class="dialog_footer">
<slot name="footer"></slot>
</div>
</div>
</teleport>
</template>
Наконец в дочернем компонентеHeader.vue
используется вDialog
Компонент здесь в основном демонстрирует использование Телепорта, а не относящийся к делу код опущен.header
компоненты
<div class="header">
...
<navbar />
<Dialog v-if="dialogVisible"></Dialog>
</div>
...
Эффект рендеринга Dom следующий:изображение.png
Как видите, мы используемteleport
компоненты, черезto
свойство, указывающее, где компонент визуализируется с помощью<div id="app"></div>
На том же уровне, т.body
вниз, ноDialog
положение делdialogVisible
Опять же, он полностью контролируется внутренними компонентами Vue.
Suspense
Suspense
Это новая функция в Vue3.x, так для чего она нужна? Не волнуйтесь, давайте разберемся с его ролью в некоторых сценариях в Vue2.x.
Во Vue2.x часто должен встречаться такой сценарий:
<template>
<div>
<div v-if="!loading">
...
</div>
<div v-if="loading">
加载中...
</div>
</div>
</template>
Когда интерфейс и сервер получают данные в интерактивном режиме, это асинхронный процесс.Как правило, мы предоставляем анимацию загрузки для совместной работы при возврате данных.v-if
для управления отображением данных.
если вы использовалиvue-async-manager
Этот плагин для выполнения вышеуказанных требований, выSuspense
Это не может быть незнакомым, Vue3.x выглядит как ссылкаvue-async-manager
.
Новые встроенные компоненты Vue3.xSuspense
, он обеспечивает дваtemplate
слот, содержимое в резервном состоянии будет отображаться в начале, а официальное содержимое в состоянии по умолчанию не будет отображаться до тех пор, пока не будет достигнуто определенное условие.Suspense
Асинхронный рендеринг компонентов для презентации намного проще. ::: предупреждение при использованииSuspense
, чтобы вернуть обещание :::Suspense
Использование компонентов:
<Suspense>
<template #default>
<async-component></async-component>
</template>
<template #fallback>
<div>
Loading...
</div>
</template>
</Suspense>
asyncComponent.vue
:
<<template>
<div>
<h4>这个是一个异步加载数据</h4>
<p>用户名:{{user.nickname}}</p>
<p>年龄:{{user.age}}</p>
</div>
</template>
<script>
import { defineComponent } from "vue"
import axios from "axios"
export default defineComponent({
setup(){
const rawData = await axios.get("http://xxx.xinp.cn/user")
return {
user: rawData.data
}
}
})
</script>
Из приведенного выше кодаSuspense
Просто компонент со слотом, указан только его слотdefault
а такжеfallback
два состояния.
Фрагмент
В Vue2.x,template
Допускается только один корневой узел:
<template>
<div>
<span></span>
<span></span>
</div>
</template>
Но в Vue3.x вы можете напрямую написать несколько корневых узлов, разве это не круто:
<template>
<span></span>
<span></span>
</template>
Лучшее встряхивание деревьев
Vue3.x учитываетtree-shaking
Глобальный и внутренний API реконструируются на основе , и в результате текущий глобальный API должен пройтиES Module
именованная ссылка, например, в Vue2.x нам нужно использоватьnextTick
:
// vue2.x
import Vue from "vue"
Vue.nextTick(()=>{
...
})
Vue.nextTick()
представляет собой глобальный API, доступный непосредственно из объекта Vue, на самом деле$nextTick()
ТолькоVue.nextTick()
Простая оболочка для функции обратного вызова последней только для удобства.this
привязан к текущему экземпляру. Хотя мы используемwebpack
изtree-shaking
, но независимо от того, используем ли мы на самом делеVue.nextTick()
, все они попадают в наш производственный код, а поскольку экземпляр Vue экспортируется как единый объект, упаковщик не может настаивать на том, какие свойства объекта всегда используются кодом.
Переписано на Vue3.x так:
import { nextTick } from "vue"
nextTick(() =>{
...
})
Затронутый API
Это большое изменение, так как предыдущий глобальный API теперь можно импортировать только по имени. Это изменение затрагивает следующие API:
Vue.nextTick
-
Vue.observable
(использоватьVue.reactive
заменять) Vue.version
-
Vue.compile
(доступно только в полной версии) -
Vue.set
(Доступно только в версиях, совместимых с 2.x) -
Vue.delete
(то же, что и выше)
Встроенные инструменты
В дополнение к вышеперечисленному API существует множество встроенных компонентов.
Вышеизложенное относится только кES Modules
сборок, связующие для поддержки древовидной структуры — сборки UMD по-прежнему включают в себя все функции и предоставляют все в глобальных переменных Vue (компилятор будет генерировать соответствующий вывод для использования внешних API вместо импорта). :::
Впереди некоторые новые функции Vue3.0, а затем я сосредоточусь на изменениях по сравнению с Vue2.x?
изменять
синтаксис именованного слота
В Vue2.x способ написания именованного слота:
<!-- 子组件中:-->
<slot name="title"></slot>
В родительском компоненте используйте:
<template slot="title">
<h1>歌曲:成都</h1>
<template>
если мы хотимЧтобы привязать данные к слоту, вы можете использовать слоты с областью видимости., реализуется следующим образом:
// 子组件
<slot name="content" :data="data"></slot>
export default {
data(){
return{
data:["走过来人来人往","不喜欢也得欣赏","陪伴是最长情的告白"]
}
}
}
<!-- 父组件中使用 -->
<template slot="content" slot-scope="scoped">
<div v-for="item in scoped.data">{{item}}</div>
<template>
Именованные слоты и слоты с заданной областью используются отдельно в Vue2.x.slot
а такжеslot-scope
Для достижения в Vue3.0 будетslot
а такжеslot-scope
Согласие на использование суммируется.
В Vue3.0v-slot
:
<!-- 父组件中使用 -->
<template v-slot:content="scoped">
<div v-for="item in scoped.data">{{item}}</div>
</template>
<!-- 也可以简写成: -->
<template #content="{data}">
<div v-for="item in data">{{item}}</div>
</template>
Пользовательская директива
Давайте сначала рассмотрим реализацию пользовательской директивы в Vue 2:
// 注册一个全局自定义指令 `v-focus`
Vue.directive('focus', {
// 当被绑定的元素插入到 DOM 中时……
inserted: function (el) {
// 聚焦元素
el.focus()
}
})
В Vue 2 пользовательские директивы создаются с помощью следующих необязательных хуков:
- bind: вызывается только один раз, когда директива впервые привязывается к элементу. Здесь можно выполнить одноразовые настройки инициализации.
- вставленный: вызывается, когда связанный элемент вставляется в родительский узел (гарантируется существование только родительского узла, но не обязательно вставленного в документ).
- update: вызывается при обновлении VNode компонента, но может произойти до обновления его дочерних VNode. Значение инструкции может измениться, а может и не измениться. Но вы можете игнорировать ненужные обновления шаблона, сравнив значения до и после обновления (подробнее о параметрах функции хука см. ниже).
- componentUpdated: вызывается после VNode компонента, в котором обновляются инструкция и ее дочерние VNode.
- Развинтируйте: вызывают только один раз, когда инструкция - это уничтожение из элемента.
В Vue 3 API пользовательских директив был изменен более семантически, как и изменения жизненного цикла компонентов, все для улучшения семантики, изменения заключаются в следующем:Итак, в Vue3 вы можете настроить директиву следующим образом:
const { createApp } from "vue"
const app = createApp({})
app.directive('focus', {
mounted(el) {
el.focus()
}
})
Затем новый можно использовать для любого элемента в шаблоне.v-focus
инструкции следующим образом:
<input v-focus />
обновление v-модели
Узнал перед использованием Vue 3v-model
Произошло очень много изменений.После его использования мы действительно можем получить эти изменения.Давайте посмотрим,какие изменения произошли,а потом поговорим о том,как их использовать:
- Изменено: использование на пользовательских компонентах
v-model
, имена свойств и событий по умолчанию изменены - изменять:
v-bind
из.sync
Модификаторы снова были удалены в Vue 3, объединены вv-model
внутри - Новое: один и тот же компонент можно установить несколько одновременно.
v-model
- Новое: разработчики могут настраивать
v-model
модификатор
Смущенный? Не волнуйтесь, см. ниже В Vue2 используйте на компонентахv-model
По сути, это эквивалентно прохождениюvalue
свойства и триггерыinput
мероприятие:
<!-- Vue 2 -->
<search-input v-model="searchValue"><search-input>
<!-- 相当于 -->
<search-input :value="searchValue" @input="searchValue=$event"><search-input>
В настоящее времяv-model
можно связать только для компонентовvalue
свойства, то мы не довольны, мы как бы используем другое свойство для наших собственных компонентов, и мы не хотим запускатьinput
чтобы обновить значение, в.sync
До того, как он вышел, он был реализован в Vue 2 следующим образом:
// 子组件:searchInput.vue
export default {
model:{
prop: 'search',
event:'change'
}
}
После модификации компонент searchInput используетv-model
эквивалентно этому:
<search-input v-model="searchValue"><search-input>
<!-- 相当于 -->
<search-input :search="searchValue" @change="searchValue=$event"><search-input>
Однако в реальной разработке в некоторых сценариях нам может понадобиться "двухсторонняя привязка" реквизита.В качестве примера приведу самый распространенный модал: модальный вполне подходит для двустороннего связывания свойств, а внешний может управлять компонентаvisible
Показать или скрыть, внутреннее закрытие компонента можно контролироватьvisible
Свойство скрыто, а видимое свойство синхронно переносится наружу. внутри компонента, когда мы закрываемmodal
, запустить событие в дочернем компоненте в шаблоне update:PropName:
this.$emit('update:visible', false)
Затем в родительском компоненте вы можете прослушать это событие, чтобы обновить данные:
<modal :visible="isVisible" @update:visible="isVisible = $event"></modal>
На этом этапе мы также можем использоватьv-bind.sync
для упрощения реализации:
<modal :visible.sync="isVisible"></modal>
Приведенный выше обзор Vue2v-model
реализация и двусторонняя привязка свойств компонента, тоКак это должно быть реализовано в Vue 3?В Vue3 используйте пользовательский компонентv-model
, что эквивалентно передачеmodelValue
свойство, вызываяupdate:modelValue
мероприятие:
<modal v-model="isVisible"></modal>
<!-- 相当于 -->
<modal :modelValue="isVisible" @update:modelValue="isVisible = $event"></modal>
Если вы хотите связать имя свойства, просто дайтеv-model
Просто передайте один параметр, и вы можете привязать несколько одновременноv-model
:
<modal v-model:visible="isVisible" v-model:content="content"></modal>
<!-- 相当于 -->
<modal
:visible="isVisible"
:content="content"
@update:visible="isVisible"
@update:content="content"
/>
Я не знаю, заметили ли вы, это написание полностью отсутствует.sync
Что случилось, так что снова упал в Vue 3.sync
орфография, универсальное использованиеv-model
Асинхронные компоненты
Используется в Vue3defineAsyncComponent
Определение асинхронных компонентов, настройка параметровcomponent
заменитьloader
, Сама функция загрузчика больше не принимает параметры разрешения и отклонения и должна возвращать обещание, которое используется следующим образом:
<template>
<!-- 异步组件的使用 -->
<AsyncPage />
</tempate>
<script>
import { defineAsyncComponent } from "vue";
export default {
components: {
// 无配置项异步组件
AsyncPage: defineAsyncComponent(() => import("./NextPage.vue")),
// 有配置项异步组件
AsyncPageWithOptions: defineAsyncComponent({
loader: () => import(".NextPage.vue"),
delay: 200,
timeout: 3000,
errorComponent: () => import("./ErrorComponent.vue"),
loadingComponent: () => import("./LoadingComponent.vue"),
})
},
}
</script>
Справочная статья:
- Руководство по началу работы с Vue3 Family Bucket
- Изучите волну новых функций Vue3
- Новые функции Vue3.0 и сводка изменений в использовании (используется в реальной работе)
- Потрясающий Vue3
Идея ума
Потратьте время, чтобы разобраться в направлениях знаний, которые соответствуют пути роста фронтенд-инженеров, как можно чаще делитесь некоторыми сводками опыта с отраслью, а также систематически анализируйте и консолидируйте себя.
Для облегчения чтения и понимания код этой статьи был загруженGithub
Если в тексте есть какие-либо ошибки, вы можете исправить их в области комментариев, если они вам полезны, ставьте лайк и подписывайтесь~~~