Недавно Vue официально объявила о самых важных функциях Vue 3.0.RFC: API функционального компонента, и выпустил плагин, совместимый с Vue 2.0:vue-function-api, который можно использовать для предварительного ознакомления с API-интерфейсом функционального компонента Vue 3.0. В целях обучения автор заранее попробовал это в проектеvue-function-api.
Автор планирует написать две статьи.Эта статья является первой статьей плана автора, в основном для изучения автором опыта работы с Vue Function API. Второй план - писать и читатьvue-function-apiОсновные принципы кода, в том числеsetup
,observable
,lifecycle
.
Время чтения этой статьи около 15-20 минут.
Обзор
Vue 2.x и предыдущие компоненты более высокого уровня будут сталкиваться с некоторыми проблемами более или менее, особенно в проектах, которые должны иметь дело с повторяющейся логикой, как только разработчик хорошо организует структуру проекта, код компонента, скорее всего, будет уничтожен. это как "код клея". Во Vue 2.x и предыдущих версиях решение таких проблем примерно по следующей схеме:
Проект, поддерживаемый автором, должен обрабатывать много мультиплексной логики.До этого автор пытался использоватьmixin
способ достижения повторного использования компонентов. Некоторые проблемы также сбивали с толку разработчиков и сопровождающих, например, компонент одновременноmixin
Несколько компонентов, трудно различить, где написаны соответствующие свойства или методыmixin
внутри. Второй,mixin
Конфликты пространств имен также могут вызывать проблемы. Трудно гарантировать разныеmixin
Одно и то же имя свойства не используется. С этой целью официальная команда выдвинула проект для комментариев по функциональному письму, которыйRFC: API функционального компонента. Используя метод функционального написания, вы можете более гибко повторно использовать компоненты.При организации компонентов высокого уровня разработчикам не нужно учитывать повторное использование в организации компонентов, и они могут лучше сосредоточиться на разработке самих функций.
Примечание. Эта статья используется только авторомvue-function-apiПолучите раннее представление о Vue Function API, который является только RFC для Vue 3.0, а не окончательным Vue 3.x API. Возможны несоответствия после публикации.
Использование в Vue 2.x
быть заранееVue 2.x
Чтобы использовать Vue Function API в Vue Function API, вам необходимо ввестиvue-function-api, основной метод введения заключается в следующем:
import Vue from 'vue';
import { plugin as VueFunctionApiPlugin } from 'vue-function-api';
Vue.use(VueFunctionApiPlugin);
Пример базового компонента
Начнем с простого примера:
<template>
<div>
<span>count is {{ count }}</span>
<span>plusOne is {{ plusOne }}</span>
<button @click="increment">count++</button>
</div>
</template>
<script>
import Vue from 'vue';
import { value, computed, watch, onMounted } from 'vue-function-api';
export default {
setup(props, context) {
// reactive state
const count = value(0);
// computed state
const plusOne = computed(() => count.value + 1);
// method
const increment = () => {
count.value++;
};
// watch
watch(
() => count.value * 2,
val => {
console.log(`count * 2 is ${val}`);
}
);
// lifecycle
onMounted(() => {
console.log(`mounted`);
});
// expose bindings on render context
return {
count,
plusOne,
increment,
};
},
};
</script>
Детальное объяснение
setup
setup
Функция является основной логикой метода написания функционала, построенного Vue Function API.При создании компонента он будет вызван.Функция принимает два параметра, которые передаются родительским компонентом.props
и контекст текущего компонентаcontext
. Глядя на следующий пример, вы можете видеть, чтоcontext
Следующие значения свойств можно получить в:
const MyComponent = {
props: {
name: String
},
setup(props, context) {
console.log(props.name);
// context.attrs
// context.slots
// context.refs
// context.emit
// context.parent
// context.root
}
}
value & state
value
Функция создает объект пакета, содержащий адаптивное свойство.value
:
Так зачем использоватьvalue
Ну потому что вJavaScript
Ссылки на базовый тип нет.Чтобы обеспечить отзывчивость свойства, его можно реализовать только с помощью объекта-обертки.Преимущество этого в том, что состояние компонента будет сохранено по ссылке, так что можно использовать вsetup
Вызываемые функции разных модулей передаются в виде параметров, что позволяет не только повторно использовать логику, но и легко реализовать отзывчивость.
Чтобы получить значение объекта-оболочки напрямую, вы должны использовать.value
, однако, если объект-оболочка используется как свойство другого реактивного объекта,Vue
внутренний пройдетproxyдля автоматического расширения объекта-оболочки. При этом в контексте отрисовки шаблона он также будет автоматически расширен.
import { state, value } from 'vue-function-api';
const MyComponent = {
setup() {
const count = value(0);
const obj = state({
count,
});
console.log(obj.count) // 作为另一个响应式对象的属性,会被自动展开
obj.count++ // 作为另一个响应式对象的属性,会被自动展开
count.value++ // 直接获取响应式对象,必须使用.value
return {
count,
};
},
template: `<button @click="count++">{{ count }}</button>`,
};
Если определенное состояние не нужно реактивно изменять в другой функции, его можно изменить с помощьюstate
Создайте реактивный объект, этоstate
Созданный реактивный объект не является объектом-оболочкой и его не нужно использовать.value
чтобы получить значение.
watch & computed
watch
а такжеcomputed
Основные понятия Vue 2.xwatch
а такжеcomputed
последовательный,watch
Может использоваться для отслеживания изменений состояния для выполнения некоторых последующих действий,computed
Используется для вычисляемых свойств, для пересчета зависимых свойств при изменениях.
computed
Возвращает объект-оболочку, доступный только для чтения, к которому можно получить доступ как к обычному объекту-оболочке.setup
функция возвращает, поэтому ее можно использовать в контексте шаблонаcomputed
Атрибуты. Может принимать два параметра, первый параметр возвращает текущее вычисленное значение свойства, когда передается второй параметр,computed
доступен для записи.
import { value, computed } from 'vue-function-api';
const count = value(0);
const countPlusOne = computed(() => count.value + 1);
console.log(countPlusOne.value); // 1
count.value++;
console.log(countPlusOne.value); // 2
// 可写的计算属性值
const writableComputed = computed(
// read
() => count.value + 1,
// write
val => {
count.value = val - 1;
},
);
watch
первый параметр иcomputed
Аналогично, возвращает значение свойства отслеживаемого объекта-оболочки, но необходимо передать два дополнительных параметра: второй параметр — это функция обратного вызова, которая срабатывает при изменении источника данных, а третий параметр —options
. Его поведение по умолчанию отличается от Vue 2.x:
- lazy: будет ли функция обратного вызова вызываться один раз при создании компонента.В отличие от Vue 2.x, lazy по умолчанию имеет значение false и будет вызываться один раз при создании компонента по умолчанию.
- deep: соответствует глубине Vue 2.x
- Flush: Существует три дополнительных значения, соответственно, «Post» (после рендеринга того, что NextTick после функции обратного вызова), «Pre» (перед рендерингом, которые вызывают функцию обратного вызова перед NextTick), «синхронизм» (синхронный триггер). Значение по умолчанию - «Post».
// double 是一个计算包装对象
const double = computed(() => count.value * 2);
watch(double, value => {
console.log('double the count is: ', value);
}); // -> double the count is: 0
count.value++; // -> double the count is: 2
когдаwatch
При наличии нескольких обернутых свойств объекта параметры могут быть переданы в виде массива.vm.$watch
Такой же,watch
Вернуть функцию, которая отменяет прослушивание:
const stop = watch(
[valueA, () => valueB.value],
([a, b], [prevA, prevB]) => {
console.log(`a is: ${a}`);
console.log(`b is: ${b}`);
}
);
stop();
Примечание: вRFC: API функционального компонентаВ первом наброске упоминалосьeffect-cleanup, который используется для устранения некоторых побочных эффектов особого случая, был отменен в предложении.
Жизненный цикл
Все существующие жизненные циклы имеют соответствующие функции-ловушки черезonXXX
создается в виде , но с одним отличием,destoryed
Необходимо использовать функцию ловушкиunmounted
заменять:
import { onMounted, onUpdated, onUnmounted } from 'vue-function-api';
const MyComponent = {
setup() {
onMounted(() => {
console.log('mounted!');
});
onUpdated(() => {
console.log('updated!');
});
// destroyed 调整为 unmounted
onUnmounted(() => {
console.log('unmounted!');
});
},
};
некоторые размышления
Приведенное выше подробное объяснение в основном извлекает общие части Vue Function API, а неRFC: API функционального компонентавсе они, такие как внедрение зависимостей в них,TypeScript
Введите вывод и другие преимущества, здесь из-за ограниченного места, если вы хотите узнать больше друзей, вы можете нажатьRFC: API функционального компонентаПроверить. люди такжеФорум обсуждения API функциональных компонентовУвидел еще комментарии:
-
Благодаря базовой конструкции, в
setup
не могу понятьЭкземпляр компонента этоЯ также столкнулся с этой проблемой, когда пытался испытать ее. Я с нетерпением жду официально выпущенного Vue 3.x, чтобы решить эту проблему. -
Для значений примитивных типов необходимо использовать объекты-обертки: в области обсуждения RFC, чтобы гарантировать и то, и другое
TypeScript
Вывод типов, повторное использование и сохранениеVue
Для прослушивателей данных свойство обертки должно быть использовано.value
Чтобы получить значение, это самая горячая дискуссия -
Об упаковке объектов
value
а такжеstate
Нечеткое наименование методов может привести к таким проблемам, как введение разработчиков в заблуждение.Amendment proposal to Function-based Component APIОбсуждения развернулись в этом предложении:
setup() {
const state = reactive({
count: 0,
});
const double = computed(() => state.count * 2);
function increment() {
state.count++;
}
return {
...toBindings(state), // retains reactivity on mutations made to `state`
double,
increment,
};
}
- представлять
reactive
API иbinding
API, гдеreactive
API похож наstate
API,binding
API похож наvalue
API. - имя метода, использованное ранее
state
В Vue 2.x он может использоваться как объект состояния компонента, что приводит к конфликту пространств имен переменных.Команда считает, что это будетstate
API переименованreactive
более элегантный. Разработчики могут писатьconst state = ...
, то черезstate.xxxx
Этот способ получить состояние компонента относительно естественен. -
value
Когда метод используется для инкапсуляции базового типа, он выглядит менее элегантным..value
В случае , разработчик может забыть использовать значение объекта-оболочки напрямую..value
, поправка, предложеннаяreactive
API, что означает создание реактивных объектов, инициализацию состоянияstate
просто используйтеreactive
создается, что сохраняетgetter
а такжеsetter
, который не только удовлетворяет дедукции типов, но и сохраняет реактивные ссылки, так что ссылки на значения состояния могут совместно использоваться разными модулями. - но
reactive
Это может вызвать следующие проблемы и должно быть введеноbinding
API. решить, как использоватьreactive
Создан реактивный объект, используйте на нем оператор распространения...
, объектgetter
а такжеsetter
,поставкаtoBindings
Реактивные методы, сохраняющие состояние.
В следующей статье автор прочитаетvue-function-apiОсновная часть принципа кода, в том числеsetup
,observable
,lifecycle
И т. д., изучите, что Vue Function API может дать нам изнутри.
Конечно, текущий API функций Vue все еще находится в стадии обсуждения, а Vue 3.0 все еще находится в стадии разработки.Давайте с нетерпением ждем первой версии Vue 3.0 во второй половине года, надеясь преподнести нам больше сюрпризов.