Предварительная версия Vue 3.0, знакомство с Vue Function API

внешний интерфейс Vue.js
Предварительная версия Vue 3.0, знакомство с Vue Function API

Недавно 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,
    };
}
  • представлятьreactiveAPI иbindingAPI, гдеreactiveAPI похож наstateAPI,bindingAPI похож наvalueAPI.
  • имя метода, использованное ранееstateВ Vue 2.x он может использоваться как объект состояния компонента, что приводит к конфликту пространств имен переменных.Команда считает, что это будетstateAPI переименованreactiveболее элегантный. Разработчики могут писатьconst state = ..., то черезstate.xxxxЭтот способ получить состояние компонента относительно естественен.
  • valueКогда метод используется для инкапсуляции базового типа, он выглядит менее элегантным..valueВ случае , разработчик может забыть использовать значение объекта-оболочки напрямую..value, поправка, предложеннаяreactiveAPI, что означает создание реактивных объектов, инициализацию состоянияstateпросто используйтеreactiveсоздается, что сохраняетgetterа такжеsetter, который не только удовлетворяет дедукции типов, но и сохраняет реактивные ссылки, так что ссылки на значения состояния могут совместно использоваться разными модулями.
  • ноreactiveЭто может вызвать следующие проблемы и должно быть введеноbindingAPI. решить, как использоватьreactiveСоздан реактивный объект, используйте на нем оператор распространения..., объектgetterа такжеsetter,поставкаtoBindingsРеактивные методы, сохраняющие состояние.

В следующей статье автор прочитаетvue-function-apiОсновная часть принципа кода, в том числеsetup,observable,lifecycleИ т. д., изучите, что Vue Function API может дать нам изнутри.

Конечно, текущий API функций Vue все еще находится в стадии обсуждения, а Vue 3.0 все еще находится в стадии разработки.Давайте с нетерпением ждем первой версии Vue 3.0 во второй половине года, надеясь преподнести нам больше сюрпризов.