Vue3.0 был обновлен и оптимизирован с момента выпуска первой версии One Piece в сентябре 2020 года; также была выпущена официальная документация китайской версии; тогда, как конечные пользователи, давайте посмотрим, какие функции и возможности были добавлены к Vue3.
Эта статья была впервые опубликована в публичном аккаунте
【前端壹读】, для более интересного контента, пожалуйста, обратите внимание на последние новости официального аккаунта.
Ю Да поделился несколькими яркими моментами Vue3.0 во время прямой трансляции на станции B:
- Производительность: оптимизация производительности
- Поддержка встряхивания дерева: поддержка оптимизации встряхивания дерева
- API композиции: API композиции
- Фрагмент, телепорт, саспенс: добавлены компоненты
- Улучшенная поддержка TypeScript: Улучшенная поддержка TypeScript
- API пользовательского рендерера: Пользовательский рендерер
С точки зрения производительности, по сравнению с Vue2.x, производительность улучшена примерно в 1,3~2 раза, упакованный объем также меньше, если вы пишете HelloWorld для упаковки, это всего 13,5 КБ, плюс все функции времени выполнения, это всего 22,5кб.
Итак, как конечные пользователи, в чем разница между нами и Vue2.x при разработке?Talk is cheap, давайте снова посмотрим на код.
Tree-shaking
Одним из наиболее важных изменений в Vue3 является введение Tree-Shaking, Меньший размер пакета, обеспечиваемый Tree-Shaking, очевиден. В версии 2.x многие функции монтируются в глобальный объект Vue, напримерSet и другие функции, поэтому, хотя мы можем их не использовать, пока vue вводится во время упаковки, эти глобальные функции все равно будут упакованы в бандл.
В Vue3 все API вводятся через модульность ES6, так что инструменты упаковки, такие как webpack или rollup, могут исключить неиспользуемые API при упаковке и минимизировать размер пакета; мы используем его только в main.js. Такие изменения можно найти:
//src/main.js
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
const app = createApp(App);
app.use(router).mount("#app");
Создайте экземпляр приложения из оригиналаnew Vue()Он создается с помощью функции createApp, однако некоторые основные функции, такие как алгоритм обновления virtualDOM и отзывчивая система, будут упакованы в любом случае; изменения, вызванные этим, — это компоненты (Vue. Vue.directive), миксин (Vue.mixin ), а плагины (Vue.use) стали методами, которые напрямую монтируются на инстансе, мы вызываем его через созданный инстанс, и преимущество в том, что приложение может иметь несколько инстансов Vue, конфигурация между разными инстансами не повлияет на каждый разное:
const app = createApp(App)
app.use(/* ... */)
app.mixin(/* ... */)
app.component(/* ... */)
app.directive(/* ... */)
Таким образом, Vue2.x также необходимо изменить следующий глобальный API. Введен модуль ES6:
- Vue.nextTick
- Вместо этого Vue.observable больше не поддерживает
reactive - Vue.version
- Vue.compile (только полная сборка)
- Vue.set (только совместимые сборки)
- Vue.delete (только совместимые сборки)
Кроме того, vuex и vue-router также использовали Tree-Shaking для улучшения, но синтаксис API не сильно изменился:
//src/store/index.js
import { createStore } from "vuex";
export default createStore({
state: {},
mutations: {},
actions: {},
modules: {},
});
//src/router/index.js
import { createRouter, createWebHistory } from "vue-router";
const router = createRouter({
history: createWebHistory(process.env.BASE_URL),
routes,
});
Подробнее об использовании Tree-Shaking можно узнать вПолный анализ конфигурации WebpackПосмотреть в.
функция жизненного цикла
Мы все знаем, что в Vue2.x есть 8 функций жизненного цикла:
- beforeCreate
- created
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeDestroy
- destroyed
В vue3 появился новыйsetupФункция жизненного цикла, время выполнения настройки находится вbeforeCreateВыполняется перед функцией жизни, поэтому его нельзя передать в эту функциюthisдля получения экземпляра, в то же время для унификации именованияbeforeDestroyпереименовать вbeforeUnmount,destroyedпереименовать вunmounted, поэтому vue3 имеет следующие функции жизненного цикла:
- beforeCreate (вместо этого рекомендуется использовать настройку)
- создано (вместо этого рекомендуется использовать настройку)
- setup
- beforeMount
- mounted
- beforeUpdate
- updated
- beforeUnmount
- unmounted
В то же время vue3 добавил хуки жизненного цикла, Мы можем добавить хуки жизненного цикла до того, как заработает жизненный цикл.onЧтобы получить доступ к жизненному циклу компонента, мы можем использовать следующие хуки жизненного цикла:
- onBeforeMount
- onMounted
- onBeforeUpdate
- onUpdated
- onBeforeUnmount
- onUnmounted
- onErrorCaptured
- onRenderTracked
- onRenderTriggered
Так как же вызывать эти функции ловушек? Мы монтируем хук жизненного цикла в настройке, и когда соответствующий жизненный цикл выполняется, вызывается соответствующая функция хука:
import { onBeforeMount, onMounted } from "vue";
export default {
setup() {
console.log("----setup----");
onBeforeMount(() => {
// beforeMount代码执行
});
onMounted(() => {
// mounted代码执行
});
},
}
Добавлен функционал
После разговора о жизненном цикле, вот новые функции, которые мы с нетерпением ждем в Vue3.
Реактивный API
мы вУглубленное изучение Object.defineProperty и ProxyЯ объяснил преимущества прокси и почему Vue3 использует прокси для реализации отзывчивости. В то же время Vue3 также тезисывает некоторые адаптивные API для лучшего повторного использования кода.
мы можем использоватьreactiveЧтобы создать реактивное состояние для объектов JS:
import { reactive, toRefs } from "vue";
const user = reactive({
name: 'Vue2',
age: 18,
});
user.name = 'Vue3'
Реактивный эквивалентен Vue2.xVue.observable.
Реактивная функция принимает только сложные типы данных, такие как объект и массив.
Для некоторых базовых типов данных, таких как строки и числа, мы хотим сделать их реактивными.Конечно, мы также можем создавать объекты с помощью реактивных функций, но Vue3 предоставляет другую функцию.ref:
import { ref } from "vue";
const num = ref(0);
const str = ref("");
const male = ref(true);
num.value++;
console.log(num.value);
str.value = "new val";
console.log(str.value);
male.value = false;
console.log(male.value);
Отзывчивый объект, возвращаемый ref, представляет собой объект RefImpl, который содержит только параметр с именем value.Он получен и изменен в js через его атрибут value.Однако при отображении в шаблоне внутреннее значение автоматически расширяется, поэтому оно не нужно добавлять в шаблон.value.
<template>
<div>
<span>{{ count }}</span>
<button @click="count ++">Increment count</button>
</div>
</template>
<script>
import { ref } from 'vue'
export default {
setup() {
const count = ref(0)
return {
count
}
}
}
</script>
Reactive в основном отвечает за сложные структуры данных, тогда как ref в основном имеет дело с базовыми структурами данных; но многие детские ботиночки неправильно поймут, что ref может обрабатывать только базовые данные, а сам ref также может обрабатывать объекты и массивы:
import { ref } from "vue";
const obj = ref({
name: "qwe",
age: 1,
});
setTimeout(() => {
obj.value.name = "asd";
}, 1000);
const list = ref([1, 2, 3, 4, 6]);
setTimeout(() => {
list.value.push(7);
}, 2000);
Когда мы имеем дело со свойствами некоторых больших реактивных объектов, мы хотели бы использовать деструктуризацию ES6, чтобы получить нужные нам значения:
let book = reactive({
name: 'Learn Vue',
year: 2020,
title: 'Chapter one'
})
let {
name,
} = book
name = 'new Learn'
// Learn Vue
console.log(book.name);
Но, к сожалению, это устранит его реактивность; в этом случае мы можем преобразовать реактивный объект в набор ссылок, которые сохранят реактивную ассоциацию с исходным объектом:
let book = reactive({
name: 'Learn Vue',
year: 2020,
title: 'Chapter one'
})
let {
name,
} = toRefs(book)
// 注意这里解构出来的name是ref对象
// 需要通过value来取值赋值
name.value = 'new Learn'
// new Learn
console.log(book.name);
Для некоторых данных только для чтения мы хотим предотвратить любые изменения в них, что можно сделать с помощьюreadonlyПриходите создать объект только для чтения:
import { reactive, readonly } from "vue";
let book = reactive({
name: 'Learn Vue',
year: 2020,
title: 'Chapter one'
})
const copy = readonly(book);
//Set operation on key "name" failed: target is readonly.
copy.name = "new copy";
Иногда нужное нам значение зависит от состояния других значений, в vue2.x мы используемcomputed函数Для вычисления свойств вычисляемая функция извлекается в vue 3. Она принимает функцию-получатель и создает получатель для значения, возвращаемого получателем.неизменныйОтзывчивый объект ref:
const num = ref(0);
const double = computed(() => num.value * 2);
num.value++;
// 2
console.log(double.value);
// Warning: computed value is readonly
double.value = 4
Или мы можем использовать функции get и set для создания объекта ref для чтения и записи:
const num = ref(0);
const double = computed({
get: () => num.value * 2,
set: (val) => (num.value = val / 2),
});
num.value++;
// 2
console.log(double.value);
double.value = 8
// 4
console.log(num.value);
реактивное слушание
Вычисляемому соответствует наблюдение, вычисленное — отношение «многие к одному», а наблюдение — отношение «один ко многим»; vue3 также предоставляет две функции для прослушивания изменений в источниках данных: наблюдение и наблюдение за эффектом.
Сначала мы смотрим на часы, их использование идентично параметрам часов и использованию компонентов, им нужно прослушивать источник данных, а затем выполнять определенную функцию обратного вызова, мы сначала смотрим на то, как они слушают, используют один источник данных:
import { reactive, ref, watch } from "vue";
const state = reactive({
count: 0,
});
//侦听时返回值得getter函数
watch(
() => state.count,
(count, prevCount) => {
// 1 0
console.log(count, prevCount);
}
);
state.count++;
const count = ref(0);
//直接侦听ref
watch(count, (count, prevCount) => {
// 2 0
console.log(count, prevCount, "watch");
});
count.value = 2;
Мы также можем поместить несколько значений в массив для прослушивания, и конечное значение также будет возвращено в виде массива:
const state = reactive({
count: 1,
});
const count = ref(2);
watch([() => state.count, count], (newVal, oldVal) => {
//[3, 2] [1, 2]
//[3, 4] [3, 2]
console.log(newVal, oldVal);
});
state.count = 3;
count.value = 4;
Если мы хотим прослушивать изменения свойств глубоко вложенного объекта, нам нужно установитьdeep:true:
const deepObj = reactive({
a: {
b: {
c: "hello",
},
},
});
watch(
() => deepObj,
(val, old) => {
// new hello new hello
console.log(val.a.b.c, old.a.b.c);
},
{ deep: true }
);
deepObj.a.b.c = "new hello";
Конечным результатом печати может быть измененное значение, потому что прослушивание отзывчивого объекта всегда возвращает ссылку на объект, поэтому нам нужно сделать глубокую копию значения:
import _ from "lodash";
const deepObj = reactive({
a: {
b: {
c: "hello",
},
},
});
watch(
() => _.cloneDeep(deepObj),
(val, old) => {
// new hello hello
console.log(val.a.b.c, old.a.b.c);
},
{ deep: true }
);
deepObj.a.b.c = "new hello";
Как правило, прослушивание автоматически останавливается при уничтожении компонента, но иногда мы хотим остановить его вручную до того, как компонент будет уничтожен.Вы можете вызвать функцию остановки, возвращаемую watch, чтобы остановить:
const count = ref(0);
const stop = watch(count, (count, prevCount) => {
// 不执行
console.log(count, prevCount);
});
setTimeout(()=>{
count.value = 2;
}, 1000);
// 停止watch
stop();
Так же есть функция watchEffect которую тоже можно использовать для прослушивания, но там уже часы Чем отличается этот watchEffect от часов? Основные отличия в их использовании заключаются в следующем:
- watchEffect не нужно полагаться на ручной ввод
- Watcheffect будет выполнять функцию обратного вызова при инициализации каждой инициализации.
- watchEffect не может получить исходное значение, только измененное значение
import { reactive, ref, watch, watchEffect } from "vue";
const count = ref(0);
const state = reactive({
year: 2021,
});
watchEffect(() => {
console.log(count.value);
console.log(state.year);
});
setInterval(() => {
count.value++;
state.year++;
}, 1000);
watchEffect будет автоматически выполняться один раз при загрузке страницы для отслеживания зависимых зависимостей; когда таймер срабатывает каждую 1 секунду после загрузки, watchEffect будет отслеживать изменения данных и выполняться автоматически, и каждое выполнение будет получать измененное значение.
Объединение API
API композиции (composition API) также является самой важной функцией в Vue 3. Предыдущая версия 2.x использовалаOptions API(вариант API), то есть официальное определение метода написания: данные, вычисляемые, методы, где нужно писать, где нужно писать, проблема, которую это приносит, заключается в том, что с увеличением функций код становится более и более сложные, мы видим, что код нужно повторять вверх и вниз. Горизонтальный прыжок:
На изображении выше цвет представляет функцию, мы можем видеть
Options APIФункциональный код относительно рассредоточен;Composition APIТогда логика той же функции может быть организована внутри функции, что удобно для сопровождения.
Давайте сначала посмотрим на предыдущую запись API опций:
export default {
components: {},
data() {},
computed: {},
watch: {},
mounted() {},
}
Options APIЭто означает помещать одинаковые вещи в один и тот же вариант. Когда наши данные относительно малы, этот метод организации относительно ясен, но по мере увеличения данных функциональные точки, которые мы поддерживаем, будут включать несколько данных и методов., но мы не можем понимать, какие данные и методы необходимо задействовать, часто нужно переключаться туда и обратно, чтобы найти, и даже нужно понимать логику других функций, что также затрудняет понимание и чтение компонентов.
а такжеComposition APIЧто нужно сделать, так это собрать код одной и той же функции вместе, чтобы нам нужно было поддерживать функциональную точку, не заботясь о другой логике, просто обращая внимание на текущую функцию;Composition APIпройти черезsetupВарианты организации кода:
export default {
setup(props, context) {}
};
Здесь мы видим, что он получает два параметра: props и context, props — это некоторые данные, передаваемые родительским компонентом, а context — это объект контекста, который представляет собой некоторые свойства, представленные в версии 2.x:
- attrs
- slots
- emit
Примечание. Данные реквизита также необходимо деконструировать с помощью toRefs, иначе ответные данные будут недействительными.
Давайте посмотрим на конкретное использование настройки с помощью кнопки Button:
<template>
<div>{{ state.count }} * 2 = {{ double }}</div>
<div>{{ num }}</div>
<div @click="add">Add</div>
</template>
<script>
import { reactive, computed, ref } from "vue";
export default {
name: "Button",
setup() {
const state = reactive({
count: 1,
});
const num = ref(2);
function add() {
state.count++;
num.value += 10;
}
const double = computed(() => state.count * 2);
return {
state,
double,
num,
add,
};
},
};
</script>
У многих детской обуви могут возникнуть сомнения.Разве это ничем не отличается от того, что я написал в данных и методах?Разве это не просто сведение их воедино? мы можем поставитьsetupФункции извлекаются и делятся на независимые функции, и каждая функция также может быть логически повторно использована в разных компонентах:
export default {
setup() {
const { networkState } = useNetworkState();
const { user } = userDeatil();
const { list } = tableData();
return {
networkState,
user,
list,
};
},
};
function useNetworkState() {}
function userDeatil() {}
function tableData() {}
Fragment
Так называемый Фрагмент — это фрагмент, в vue2.x каждый шаблон обязан иметь корневую ноду, поэтому наш код должен быть написан так:
<template>
<div>
<span></span>
<span></span>
</div>
</template>
Или также может быть представлен в Vue2.xvue-fragmentsбиблиотека, которая заменяет div фиктивным фрагментом; в React обходным путем является передачаReact.FragmentТег создает фиктивный элемент, в Vue3 нам может просто не понадобиться корневой узел:
<template>
<span>hello</span>
<span>world</span>
</template>
Это устраняет множество бессмысленных элементов div.
Teleport
Телепорт переводится как телепортация и передача на большие расстояния; как следует из названия, он может передавать элементы или компоненты в слотах в другие места на странице:
В React вы можете сделать это черезcreatePortalфункция для создания узла, который должен быть отправлен;Portal, но H5 роднойPortal标签Он тоже есть в планах.Хотя есть некоторые проблемы с безопасностью, во избежание дублирования имен он изменен наTeleport.
Обычный сценарий использования Teleport — передача положения модального окна в некоторые глубоко вложенные компоненты. Хотя модальное окно логически относится к этому компоненту, с точки зрения стиля и структуры DOM, оно не способствует обслуживанию (z-индекс и другие вопросы) после того, как уровень вложенности станет глубже, поэтому нам нужно его вырезать:
<template>
<button @click="showDialog = true">打开模态框</button>
<teleport to="body">
<div class="modal" v-if="showDialog" style="position: fixed">
我是一个模态框
<button @click="showDialog = false">关闭</button>
<child-component :msg="msg"></child-component>
</div>
</teleport>
</template>
<script>
export default {
data() {
return {
showDialog: false,
msg: "hello"
};
},
};
</script>
Здесь модальный div в Телепорте перенесен в нижнюю часть тела; хотя они и рендерятся в разных местах, элементы и компоненты в Телепорте по-прежнему являются логическими подкомпонентами родительского компонента, и все еще могут взаимодействовать с родителем компонент. Телепорт получает два параметраtoа такжеdisabled:
- to - строка: Должен быть допустимым селектором запроса или HTMLElement, может быть селектором идентификатора или класса и т. д.
- disabled - boolean: Если это правда, это означает, что функция телепорта отключена, и содержимое его слота не будет перемещено ни в какую позицию.По умолчанию false не отключено.
Suspense
Suspense — это встроенный компонент, запущенный Vue3, который позволяет нашей программе отображать некоторый резервный контент в ожидании асинхронных компонентов, что позволяет нам создать плавный пользовательский интерфейс; загрузка асинхронных компонентов в Vue на самом деле уже существует в Vue2.x, маршрутизация компонент, загруженный в используемый нами vue-router, на самом деле является асинхронным компонентом:
export default {
name: "Home",
components: {
AsyncButton: () => import("../components/AsyncButton"),
},
}
Переопределены в Vue3, асинхронные компоненты должны проходитьdefineAsyncComponentчтобы определить отображение:
// 全局定义异步组件
//src/main.js
import { defineAsyncComponent } from "vue";
const AsyncButton = defineAsyncComponent(() =>
import("./components/AsyncButton.vue")
);
app.component("AsyncButton", AsyncButton);
// 组件内定义异步组件
// src/views/Home.vue
import { defineAsyncComponent } from "vue";
export default {
components: {
AsyncButton: defineAsyncComponent(() =>
import("../components/AsyncButton")
),
},
};
В то время как асинхронный компонент может иметь более сложное управление:
export default {
components: {
AsyncButton: defineAsyncComponent({
delay: 100,
timeout: 3000,
loader: () => import("../components/AsyncButton"),
errorComponent: ErrorComponent,
onError(error, retry, fail, attempts) {
if (attempts <= 3) {
retry();
} else {
fail();
}
},
}),
},
};
Таким образом, мы можем контролировать загрузку асинхронных компонентов и можем перезагружать или отображать ненормальные состояния при сбое загрузки:
Вернемся к Suspense. Как упоминалось выше, он в основном отображает некоторый резервный контент при загрузке компонента. Он предоставляет два слота слота, одинdefaultПо умолчаниюfallbackСтатус загрузки:
<template>
<div>
<button @click="showButton">展示异步组件</button>
<template v-if="isShowButton">
<Suspense>
<template #default>
<AsyncButton></AsyncButton>
</template>
<template #fallback>
<div>组件加载中...</div>
</template>
</Suspense>
</template>
</div>
</template>
<script>
export default {
setup() {
const isShowButton = ref(false);
function showButton() {
isShowButton.value = true;
}
return {
isShowButton,
showButton,
};
},
}
</script>
Несовместимые функции
Несовместимые функции — это в основном некоторый синтаксис, который сильно изменился в версии Vue2.x, и могут быть проблемы совместимости с Vue3.
данные, примеси и фильтры
В Vue2.x мы можем определить данные какobjectилиfunction, но мы знаем, что если данные являются объектом в компоненте, данные будут взаимодействовать друг с другом, потому что объект является ссылочным типом данных;
В Vue3 данные принимаются толькоfunctionтип, черезfunctionвозвращаемый объект; тем временемMixinОбъединенное поведение изменилось, и когда выполняется база данных класса Mixin Class Most Copy:
const Mixin = {
data() {
return {
user: {
name: 'Jack',
id: 1,
address: {
prov: 2,
city: 3,
},
}
}
}
}
const Component = {
mixins: [Mixin],
data() {
return {
user: {
id: 2,
address: {
prov: 4,
},
}
}
}
}
// vue2结果:
{
id: 2,
name: 'Jack',
address: {
prov: 4,
city: 3
}
}
// vue3结果:
user: {
id: 2,
address: {
prov: 4,
},
}
Мы видим результат окончательного слияния, vue2.x выполнит глубокую копию, а также объединит и скопирует данные в данные вниз и вглубь; в то время как vue3 выполняет только неглубокую копию, и данные в данных обнаруживаются существующими и не будут объединены и скопированы.
В vue2.x мы также можем передать过滤器filterЧтобы обработать отображение некоторого текстового содержимого:
<template>
<div>{{ status | statusText }}</div>
</template>
<script>
export default {
props: {
status: {
type: Number,
default: 1
}
},
filters: {
statusText(value){
if(value === 1){
return '订单未下单'
} else if(value === 2){
return '订单待支付'
} else if(value === 3){
return '订单已完成'
}
}
}
}
</script>
Чаще всего приходится бороться с отображением некоторых ордеров копирайтингом, однако в vue3 фильтр filter удален и больше не поддерживается, официальная рекомендация использовать вызовы методов или计算属性computedзаменить.
v-model
В Vue2.x,v-modelэквивалентно связываниюvalueсвойства иinputСобытия, которые по сути являются синтаксическим сахаром:
<child-component v-model="msg"></child-component>
<!-- 相当于 -->
<child-component :value="msg" @input="msg=$event"></child-component>
В некоторых случаях нам нужно связать несколько значений в двух направлениях, а другие значения нужно явно изменить с помощью функции обратного вызова:
<child-component
v-model="msg"
:msg1="msg1"
@change1="msg1=$event"
:msg2="msg2"
@change2="msg2=$event">
</child-component>
Представлено в версии vue2.3.0+.syncМодификаторы, которые по сути являются синтаксическим сахаром, связаны с компонентами.@update:propNameОбратный вызов, более краткий синтаксис:
<child-component
:msg1.sync="msg1"
:msg2.sync="msg2">
</child-component>
<!-- 相当于 -->
<child-component
:msg1="msg1"
@update:msg1="msg1=$event"
:msg2="msg2"
@update:msg2="msg2=$event">
</child-component>
Генерал-лейтенант Вью3v-modelа также.syncФункция интегрирована, а .sync заброшен, что означает, что несколько значений значений двусторонней привязки могут быть напрямую переданы через несколько v-моделей; в то же время имя свойства по умолчанию, переданное v-моделью, изменено с значение в modelValue:
<child-component
v-model="msg">
</child-component>
<!-- 相当于 -->
<child-component
:modelValue="msg"
@update:modelValue="msg = $event">
</child-component>
Если мы хотим передать через v-модель несколько значений, мы можем передатьargumentПерейти к v-модели:
<child-component
v-model.msg1="msg1"
v-model.msg2="msg2">
</child-component>
<!-- 相当于 -->
<child-component
:msg1="msg1"
@update:msg1="msg1=$event"
:msg2="msg2"
@update:msg2="msg2=$event">
</child-component>
v-для и ключ
Во Vue2.x мы все знаем, что v-для каждого цикла нужно давать каждому дочернему элементу уникальный ключ, не привязанный к метке шаблона,
<template v-for="item in list">
<div :key="item.id">...</div>
<span :key="item.id">...</span>
</template>
В Vue3 значение ключа должно быть помещено в тег шаблона, чтобы нам не приходилось устанавливать его для каждого дочернего узла:
<template v-for="item in list" :key="item.id">
<div>...</div>
<span>...</span>
</template>
v-связать слияние
В vue2.x, если элемент определен одновременноv-bind="object"и идентичное отдельное свойство, то это отдельное свойство переопределяетobjectПривязки в:
<div id="red" v-bind="{ id: 'blue' }"></div>
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- 最后结果都相同 -->
<div id="red"></div>
Однако в vue3, если элемент определен одновременноv-bind="object"И идентичный индивидуальный атрибут, порядок привязки объявления определяет последний результат (последний покрывает первый):
<!-- template -->
<div id="red" v-bind="{ id: 'blue' }"></div>
<!-- result -->
<div id="blue"></div>
<!-- template -->
<div v-bind="{ id: 'blue' }" id="red"></div>
<!-- result -->
<div id="red"></div>
исх в v-для
В vue2.x используется на v-forrefсвойства, черезthis.$refsполучит массив:
<template
<div v-for="item in list" :ref="setItemRef"></div>
</template>
<script>
export default {
data(){
list: [1, 2]
},
mounted () {
// [div, div]
console.log(this.$refs.setItemRef)
}
}
</script>
Но это может быть не тот результат, который нам нужен, поэтому vue3 больше не создает массив автоматически, а превращает обработку ref в функцию, которая по умолчанию передается в ноду:
<template
<div v-for="item in 3" :ref="setItemRef"></div>
</template>
<script>
import { reactive, onUpdated } from 'vue'
export default {
setup() {
let itemRefs = reactive([])
const setItemRef = el => {
itemRefs.push(el)
}
onUpdated(() => {
console.log(itemRefs)
})
return {
itemRefs,
setItemRef
}
}
}
</script>
v-для и v-если приоритет
В vue2.x используйте как v-for, так и v-if для элемента,v-forОн имеет более высокий приоритет, поэтому для оптимизации производительности в Vue2.x важный момент заключается в том, что V-для и V-IF нельзя размещать на одном элементе.
И в vue3,v-ifСравниватьv-forимеют более высокий приоритет. Поэтому следующий код может нормально работать в vue2.x, но не тогда, когда v-if вступает в силу в vue3.itemпеременная, поэтому будет сообщено об ошибке:
<template>
<div v-for="item in list" v-if="item % 2 === 0" :key="item">{{ item }}</div>
</template>
<script>
export default {
data() {
return {
list: [1, 2, 3, 4, 5],
};
},
};
</script>
Суммировать
Выше приведены некоторые новые возможности и функции, которые мы можем включить в Vue3.0 в качестве терминала.На самом деле, в Vue3.0 еще много изменений.Из-за недостатка места мы не будем раскрывать их по одному.Вы можете проверить официальные документы самостоятельно Мы ожидаем, что Vue3 принесет нам более удобный и дружественный опыт разработки.
Для получения дополнительной информации о внешнем интерфейсе, пожалуйста, обратите внимание на общедоступный номер【前端壹读】.
Если вы думаете, что это хорошо написано, пожалуйста, следуйте за мнойДомашняя страница Наггетс. Для получения дополнительных статей, пожалуйста, посетитеБлог Се Сяофэй