Технические характеристики inoi 239 (черный)

When To Avoid This Pattern

As long as you’re vigilant in scoping prototype properties, using this pattern is quite safe — as in, unlikely to produce bugs.

However, it can sometimes cause confusion with other developers. They might see , for example, and think, “Oh, I didn’t know about this Vue feature!” Then they move to a different project and are confused when is undefined. Or, maybe they want to Google how to do something, but can’t find results because they don’t realize they’re actually using Axios under an alias.

The convenience comes at the cost of explicitness. When looking at a component, it’s impossible to tell where came from. Vue itself? A plugin? A coworker?

So what are the alternatives?

Non-Prop Attributes

A non-prop attribute is an attribute that is passed to a component, but does not have a corresponding prop defined.

While explicitly defined props are preferred for passing information to a child component, authors of component libraries can’t always foresee the contexts in which their components might be used. That’s why components can accept arbitrary attributes, which are added to the component’s root element.

For example, imagine we’re using a 3rd-party component with a Bootstrap plugin that requires a attribute on the . We can add this attribute to our component instance:

And the attribute will automatically be added to the root element of .

Replacing/Merging with Existing Attributes

Imagine this is the template for :

To specify a theme for our date picker plugin, we might need to add a specific class, like this:

In this case, two different values for are defined:

  • , which is set by the component in its template
  • , which is passed to the component by its parent

For most attributes, the value provided to the component will replace the value set by the component. So for example, passing will replace and probably break it! Fortunately, the and attributes are a little smarter, so both values are merged, making the final value: .

Disabling Attribute Inheritance

If you do not want the root element of a component to inherit attributes, you can set in the component’s options. For example:

This can be especially useful in combination with the instance property, which contains the attribute names and values passed to a component, such as:

With and , you can manually decide which element you want to forward attributes to, which is often desirable for :

Note that option does not affect and bindings.

This pattern allows you to use base components more like raw HTML elements, without having to care about which element is actually at its root:

##company## — ##description##

Edit this page on GitHub!

Alternative Patterns

When Not Using a Module System

In applications with no module system (e.g. via Webpack or Browserify), there’s a pattern that’s often used with any JavaScript-enhanced frontend: a global object.

If what you want to add has nothing to do with Vue specifically, this may be a good alternative to reach for. Here’s an example:

If you raised an eyebrow at , what it does is prevent the object from being changed in the future. This essentially makes all its properties constants, protecting you from future state bugs.

Now the source of these shared properties is more obvious: there’s an object defined somewhere in the app. To find it, developers can run a project-wide search.

Another advantage is that can now be used anywhere in your code, whether it’s Vue-related or not. That includes attaching values directly to instance options, rather than having to enter a function to access properties on :

When Using a Module System

When you have access to a module system, you can easily organize shared code into modules, then / those modules wherever they’re needed. This is the epitome of explicitness, because in each file you gain a list of dependencies. You know exactly where each one came from.

While certainly more verbose, this approach is definitely the most maintainable, especially when working with other developers and/or building a large app.

##company## — ##description##

Edit this page on GitHub!

Валидируйте формы по-простому — используйте Vuelidate

На одной из моих прошлых работ, я был уверен, что моё описание работы было таким: «Конструировать базы данных и формы». Я чувствовал себя так, как будто каждый день я делал форму после формы после формы. Но в этом был смысл. Формы — главный способ получить от пользователя информацию, и они необходимы для работы наших приложений. Это и приводит к тому, что мы регулярно делаем много форм.

Тем не менее, формы сложно реализовывать. Кажется, что писать их довольно просто, однако как только мы добавляем какую-то логику и валидацию, всё это быстро превращается в настоящий кошмар.

Именно по этой причине появился Vuelidate. Это библиотека, которая упрощает работу с проверкой форм, позволяет писать свои валидаторы, а также берёт на себя всю рутину.

Изучите как настроить Vuelidate в статье «Простая валидация форм в Vue с помощью Vulidate» от Добромира Христова.

Component Names

When registering a component, it will always be given a name. For example, in the global registration we’ve seen so far:

The component’s name is the first argument of .

The name you give a component may depend on where you intend to use it. When using a component directly in the DOM (as opposed to in a string template or single-file component), we strongly recommend following the for custom tag names (all-lowercase, must contain a hyphen). This helps you avoid conflicts with current and future HTML elements.

You can see other recommendations for component names in the .

With kebab-case

When defining a component with kebab-case, you must also use kebab-case when referencing its custom element, such as in .

With PascalCase

When defining a component with PascalCase, you can use either case when referencing its custom element. That means both and are acceptable. Note, however, that only kebab-case names are valid directly in the DOM (i.e. non-string templates).

Controlling Updates

Thanks to Vue’s Reactivity system, it always knows when to update (if you use it correctly). There are edge cases, however, when you might want to force an update, despite the fact that no reactive data has changed. Then there are other cases when you might want to prevent unnecessary updates.

Forcing an Update

If you find yourself needing to force an update in Vue, in 99.99% of cases, you’ve made a mistake somewhere.

You may not have accounted for change detection caveats or , or you may be relying on state that isn’t tracked by Vue’s reactivity system, e.g. with .

However, if you’ve ruled out the above and find yourself in this extremely rare situation of having to manually force an update, you can do so with .

Cheap Static Components with

Rendering plain HTML elements is very fast in Vue, but sometimes you might have a component that contains a lot of static content. In these cases, you can ensure that it’s only evaluated once and then cached by adding the directive to the root element, like this:

Once again, try not to overuse this pattern. While convenient in those rare cases when you have to render a lot of static content, it’s simply not necessary unless you actually notice slow rendering – plus, it could cause a lot of confusion later. For example, imagine another developer who’s not familiar with or simply misses it in the template. They might spend hours trying to figure out why the template isn’t updating correctly.

##company## — ##description##

Edit this page on GitHub!

# Отключение генерации index.html

При использовании Vue CLI с существующим бэкендом, вам может потребоваться отключить генерацию , чтобы сгенерированные ресурсы могли быть использованы с другим документом по умолчанию. Для этого добавьте в файл следующее:

Однако, это не рекомендуется потому что:

  • Жёстко заданные имена файлов затрудняют реализацию эффективного управления кэшированием.
  • Жёстко заданные имена файлов плохо работают с разделением кода, что генерирует дополнительные файлы JavaScript с различными именами файлов.
  • Жёстко заданные имена файлов не работают с .

Вместо этого вы должны использовать опцию , чтобы указать сгенерированный HTML в качестве шаблона вашего фреймворка на стороне сервера.

Создание многостраничного приложения

Не каждое приложение должно быть одностраничным (SPA). Vue CLI поддерживает создание многостраничных приложений с помощью . Код приложения будет эффективно переиспользоваться между его частями для оптимизации скорости загрузки.

Динамически добавляйте CSS-классы

Vue очень органично объединяет HTML и Javascript, однако мы не можем забывать и о CSS. CSS та вещь, которая делает наши приложения действительно красивыми, являясь при этом мощным инструментом.

Довольно общим паттерном в веб-приложениях является добавление и удаление классов в зависимости от состояния приложения. Мы делаем это, чтобы отключить кнопку, анимировать элементы вроде экранов загрузки и кучи других штук.

Vue предоставляет нам много способов для динамического добавления и удаления CSS-классов на основе событий приложения. Знание того, как это работает, поможет вам писать более изящный и эффективный код.

Майкл Тиссен написал статью, которая описывает все способы динамического добавления и удаления CSS-классов во Vue. Там рассматривается синтаксис массивов и объектов, использование javascript-выражений для вычисления css-классов и динамического добавления классов в пользовательских компонентах (вам не придётся добавлять свой prop!). Вы даже можете генерировать свои имена CSS-классов на лету!

Circular References

Recursive Components

Components can recursively invoke themselves in their own template. However, they can only do so with the option:

When you register a component globally using , the global ID is automatically set as the component’s option.

If you’re not careful, recursive components can also lead to infinite loops:

A component like the above will result in a “max stack size exceeded” error, so make sure recursive invocation is conditional (i.e. uses a that will eventually be ).

Circular References Between Components

Let’s say you’re building a file directory tree, like in Finder or File Explorer. You might have a component with this template:

Then a component with this template:

When you look closely, you’ll see that these components will actually be each other’s descendent and ancestor in the render tree — a paradox! When registering components globally with , this paradox is resolved for you automatically. If that’s you, you can stop reading here.

However, if you’re requiring/importing components using a module system, e.g. via Webpack or Browserify, you’ll get an error:

To explain what’s happening, let’s call our components A and B. The module system sees that it needs A, but first A needs B, but B needs A, but A needs B, etc. It’s stuck in a loop, not knowing how to fully resolve either component without first resolving the other. To fix this, we need to give the module system a point at which it can say, “A needs B eventually, but there’s no need to resolve B first.”

In our case, let’s make that point the component. We know the child that creates the paradox is the component, so we’ll wait until the lifecycle hook to register it:

Or alternatively, you could use Webpack’s asynchronous when you register the component locally:

Problem solved!

Programmatic Event Listeners

So far, you’ve seen uses of , listened to with , but Vue instances also offer other methods in its events interface. We can:

  • Listen for an event with
  • Listen for an event only once with
  • Stop listening for an event with

You normally won’t have to use these, but they’re available for cases when you need to manually listen for events on a component instance. They can also be useful as a code organization tool. For example, you may often see this pattern for integrating a 3rd-party library:

This has two potential issues:

  • It requires saving the to the component instance, when it’s possible that only lifecycle hooks need access to it. This isn’t terrible, but it could be considered clutter.
  • Our setup code is kept separate from our cleanup code, making it more difficult to programmatically clean up anything we set up.

You could resolve both issues with a programmatic listener:

Using this strategy, we could even use Pikaday with several input elements, with each new instance automatically cleaning up after itself:

See this example for the full code. Note, however, that if you find yourself having to do a lot of setup and cleanup within a single component, the best solution will usually be to create more modular components. In this case, we’d recommend creating a reusable component.

To learn more about programmatic listeners, check out the API for .

Note that Vue’s event system is different from the browser’s EventTarget API. Though they work similarly, , , and are not aliases for , , and .

Используйте vue-router для роутинга на клиенте

Если вы осуществляете роутинг на клиенте, то написать своё решение в целом не сложно. На самом деле это просто — сопоставить маршруты и поменять после этого компоненты.

Однако использование ещё проще! К тому же, это официальный пакет Vue, поэтому вы можете не беспокоиться по поводу совместимости и поддержки.

И как только вы начнёте работать с:

  • запросами
  • параметрами маршрута
  • вложенными маршрутами
  • динамическим сопоставлением маршрутов
  • транзишенами

…а вы, скорее всего, начнёте с этим работать, то написание своего решения станет слишком сложным, громоздким. Поэтому вместо этого читайте гайд по vue-router от Эда Зынды «Начало работы с Vue Router».

# Обработка статических ресурсов

Статические ресурсы могут обрабатываться двумя различными способами:

  • Импорт в JavaScript или указание ссылки на них в шаблоне/CSS с использованием относительных путей. Такие ресурсы будут обрабатываться webpack.

  • Расположение в каталоге и добавление ссылки на них с использованием абсолютных путей. Такие ресурсы просто копируются и не обрабатываются webpack.

Импорты относительных путей

Если вы ссылаетесь на статический ресурс, используя относительный путь (должен начинаться с ) внутри JavaScript, CSS или файлов, то он будет добавлен в дерево зависимостей webpack. В процессе компиляции все URL ресурсов, такие как , и CSS будут обрабатываться как зависимости модуля.

Например, будет преобразован в , а тег шаблона

будет скомпилирован в:

Внутри используется для определения конечного расположения файла с хэшем версии и правильный путь относительно корня, а также для инлайн-встраивания ресурсов, чей размер меньше 4 КБайт, чтобы уменьшить количество HTTP-запросов к серверу.

Изменить размер можно через . Например, чтобы установить лимит в 10 КБайт:

Правила преобразования URL

  • Если в URL абсолютный путь (например, ), он будет оставлен как есть.

  • Если URL начинается с , он будет интерпретироваться как запрос модуля относительно текущего каталога и разрешаться на основе структуры каталогов вашей файловой системы.

  • Если URL начинается с , то всё что после него будет интерпретироваться как запрос модуля. Это означает, что вы можете ссылаться на ресурсы даже внутри :

  • Если URL начинается с , то он также будет интерпретироваться как запрос модуля. Это удобно, потому что Vue CLI по умолчанию добавляет псевдоним для . (только в шаблонах)

Любые статические ресурсы в каталоге просто копируются в каталог итоговой сборки и не будут обрабатываться webpack. Вы должны ссылаться на них, используя абсолютные пути.

Обратите внимание, что мы рекомендуем импортировать ресурсы как часть дерева зависимостей модуля, чтобы они обрабатывались webpack со следующими преимуществами:

  • Скрипты и стили минифицируются и объединяются, уменьшая количество сетевых запросов.
  • Недостающие файлы вызывают ошибку сборки вместо ошибок 404 для пользователей.
  • Имена файлов в результате будут с хэшем, поэтому не нужно беспокоиться о том, что браузеры используют старые версии из кэша.

Каталог предоставляется для крайних случаев, поэтому, когда вы ссылаетесь на него по абсолютному пути, необходимо учитывать, где будет опубликовано ваше приложение. Если публикуется не в корне домена, нужно указать префикс для URL-адресов в :

  • В или других HTML-файлах, используемых в качестве шаблонов, необходимо добавлять префикс в ссылки с помощью :

  • В шаблонах потребуется сначала передать в компонент:

    А затем использовать в шаблоне:

# Веб-компонент (Web Component)

Примечание совместимости

Режим веб-компонентов не поддерживается IE11 и ниже.

Примечание зависимости Vue

В режиме веб-компонентов Vue экстернализируется. Это означает, что сборка не будет содержать Vue, даже если ваш код его импортирует. Сборка будет подразумевать, что доступен на странице в качестве глобальной переменной.

Чтобы избежать экстернализиции Vue установите флаг для команды .

Вы можете запустить сборку одной точки входа в качестве веб-компонента с помощью:

Обратите внимание, что точка входа должна быть файлом. Vue CLI автоматически обернёт и зарегистрирует компонент как веб-компонент за вас, и нет необходимости делать это самостоятельно в

Можно использовать в качестве демо-приложения исключительно для разработки.

Сборка создаст один файл JavaScript (и его минифицированную версию) содержащий всё необходимое. Скрипт, когда добавлен на странице, зарегистрирует пользовательский элемент , который оборачивает компонент Vue с помощью . Обёртка автоматически проксирует свойства, атрибуты, события и слоты. Подробнее можно узнать в документации .

Обратите внимание, что сборка зависит от глобально доступного на странице. Этот режим позволяет использовать компонент Vue как обычный элемент DOM:

Этот режим позволяет использовать компонент Vue как обычный элемент DOM:

Сборка, регистрирующая несколько веб-компонентов

При сборке веб-компонентов можно также указать несколько компонентов с помощью выражения в качестве входной точки:

При сборке нескольких веб-компонентов будет использовано в качестве префикса, а имя пользовательского элемента будет определяться именем файла компонента. Например, для и компонента , итоговый пользовательский элемент будет зарегистрирован как .

Асинхронный веб-компонент (Async Web Component)

При указании нескольких веб-компонентов, сборка может стать довольно большой, а пользователь использовать только некоторые из компонентов, которые регистрирует сборка. Режим асинхронных веб-компонентов создаёт сборку, разделённую на части, с маленьким файлом точки входа, который обеспечивает общий runtime между всеми компонентами, и заранее регистрирует все пользовательские элементы. Фактическая реализация компонента загружается по требованию, только когда экземпляр соответствующего пользовательского элемента используется на странице:

Теперь на странице пользователю необходимо только подключить Vue и файл точки входа:

.sync Modifier

In some cases, we may need “two-way binding” for a prop. Unfortunately, true two-way binding can create maintenance issues, because child components can mutate the parent without the source of that mutation being obvious in both the parent and the child.

That’s why instead, we recommend emitting events in the pattern of . For example, in a hypothetical component with a prop, we could communicate the intent of assigning a new value with:

Then the parent can listen to that event and update a local data property, if it wants to. For example:

For convenience, we offer a shorthand for this pattern with the modifier:

Note that with the modifier does not work with expressions (e.g. is invalid). Instead, you must only provide the name of the property you want to bind, similar to .

The modifier can also be used with when using an object to set multiple props at once:

This passes each property in the object (e.g. ) as an individual prop, then adds update listeners for each one.

Using with a literal object, such as in , will not work, because there are too many edge cases to consider in parsing a complex expression like this.

##company## — ##description##

Edit this page on GitHub!

One-Way Data Flow

All props form a one-way-down binding between the child property and the parent one: when the parent property updates, it will flow down to the child, but not the other way around. This prevents child components from accidentally mutating the parent’s state, which can make your app’s data flow harder to understand.

In addition, every time the parent component is updated, all props in the child component will be refreshed with the latest value. This means you should not attempt to mutate a prop inside a child component. If you do, Vue will warn you in the console.

There are usually two cases where it’s tempting to mutate a prop:

  1. The prop is used to pass in an initial value; the child component wants to use it as a local data property afterwards. In this case, it’s best to define a local data property that uses the prop as its initial value:

  2. The prop is passed in as a raw value that needs to be transformed. In this case, it’s best to define a computed property using the prop’s value:

Note that objects and arrays in JavaScript are passed by reference, so if the prop is an array or object, mutating the object or array itself inside the child component will affect parent state.

# Пре-процессоры

Вы можете выбрать пре-процессоры (Sass/Less/Stylus) при создании проекта. Если вы этого не сделали, то внутренняя конфигурация webpack всё равно настроена для их использования. Вам лишь требуется вручную доустановить соответствующие загрузчики для webpack:

Теперь вы можете импортировать соответствующие типы файлов, или использовать их синтаксис внутри файлов с помощью:

Совет по производительности Sass

Обратите внимание, при использовании Dart Sass синхронная компиляция вдвое быстрее асинхронной по умолчанию, из-за накладных расходов на асинхронные коллбэки. Чтобы избежать их можно воспользоваться пакетом fibers для вызова асинхронных импортёров по пути синхронного кода

Для этого просто установите в качестве зависимости проекта:

Также имейте в виду, поскольку это нативный модуль, то могут возникнуть различные проблемы совместимости, в зависимости от ОС и окружения сборки. В таких случаях выполните для устранения проблемы.

Автоматические импорты

Если вы хотите автоматически импортировать файлы (для цветов, переменных, примесей…), можно использовать style-resources-loader. Вот пример для stylus, который импортирует в каждый однофайловый компонент и в каждый файл stylus:

Вы также можете использовать vue-cli-plugin-style-resources-loader.

Local Registration

Global registration often isn’t ideal. For example, if you’re using a build system like Webpack, globally registering all components means that even if you stop using a component, it could still be included in your final build. This unnecessarily increases the amount of JavaScript your users have to download.

In these cases, you can define your components as plain JavaScript objects:

Then define the components you’d like to use in a option:

For each property in the object, the key will be the name of the custom element, while the value will contain the options object for the component.

Note that locally registered components are not also available in subcomponents. For example, if you wanted to be available in , you’d have to use:

Or if you’re using ES2015 modules, such as through Babel and Webpack, that might look more like:

Note that in ES2015+, placing a variable name like inside an object is shorthand for , meaning the name of the variable is both:

  • the custom element name to use in the template, and
  • the name of the variable containing the component options

# Библиотека (Library)

Примечание о зависимости Vue

В режиме библиотеки Vue экстернализируется. Это означает, что сборка не будет содержать Vue, даже если ваш код его импортирует. Если библиотека используется через сборщик, он должен попытаться загрузить Vue в качестве зависимости через сборщик; в противном случае, он должен вернуться к глобальной переменной .

Чтобы избежать экстернализиции Vue установите флаг для команды .

Вы можете запустить сборку одной точки входа в качестве библиотеки с помощью:

Точка входа может быть или файлом. Если точка входа не указана, то будет использоваться .

Сборка библиотеки сгенерирует:

  • : сборка CommonJS для использования в сборщиках (к сожалению, webpack в настоящее время пока ещё не поддерживает формат ES-модулей для сборок)

  • : сборка UMD для использования в браузерах или с AMD загрузчиками

  • : минифицированная версия UMD сборки.

  • : извлечённый CSS-файл (можно принудительно вставлять стили инлайн, установив в )


При разработке библиотеки или использования монорепозитория, имейте ввиду, что CSS-импорты являются побочными эффектами (side effects). Убедитесь, что удалили опцию из файла , в противном случае webpack будет удалять CSS-фрагменты при сборке для production.

Vue vs. JS / TS файлы точек входа

При использовании файла в качестве точки входа, библиотека будет экспортировать сам компонент Vue, потому что компонент всегда имеет экспорт по умолчанию (export default).

Однако, когда используется или файл в качестве точки входа, он может содержать именованные экспорты, поэтому библиотека будет использоваться как модуль. Это означает, что экспорт библиотеки по умолчанию должен быть доступен как в UMD сборках, или как в CommonJS сборках. Если у вас нет именованных экспортов и вы хотите использовать экспорт по умолчанию (default export), вы можете использовать следующую конфигурацию webpack в :

Prop Validation

Components can specify requirements for their props, such as the types you’ve already seen. If a requirement isn’t met, Vue will warn you in the browser’s JavaScript console. This is especially useful when developing a component that’s intended to be used by others.

To specify prop validations, you can provide an object with validation requirements to the value of , instead of an array of strings. For example:

When prop validation fails, Vue will produce a console warning (if using the development build).

Note that props are validated before a component instance is created, so instance properties (e.g. , , etc) will not be available inside or functions.

Type Checks

The can be one of the following native constructors:

  • String
  • Number
  • Boolean
  • Array
  • Object
  • Date
  • Function
  • Symbol

In addition, can also be a custom constructor function and the assertion will be made with an check. For example, given the following constructor function exists:

You could use:

to validate that the value of the prop was created with .

Ссылка на основную публикацию