Интеграция с Vue
Быстрый старт
Важно
Поддерживаемая версия Vue: не ниже 3
Подключение через top-level-await
<!DOCTYPE html>
<html>
<head>
<!-- Вместо YOUR_API_KEY подставить значение настоящего ключа -->
<script src="https://api-maps.yandex.ru/v3/?apikey=YOUR_API_KEY&lang=ru_RU"></script>
<script type="module" src="index.ts"></script>
</head>
<body>
<div id="app"></div>
</body>
</html>
import {createApp} from 'vue';
import App from './App.vue';
createApp(App).mount('#app');
<script lang="ts" setup>
import {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapMarker} from './lib/ymaps';
import type {YMapLocationRequest} from 'ymaps3';
const LOCATION: YMapLocationRequest = {
center: [37.588144, 55.733842],
zoom: 9
};
</script>
<template>
<div style="width: 600px; height: 400px">
<YMap :location="LOCATION">
<YMapDefaultSchemeLayer />
<YMapDefaultFeaturesLayer />
<YMapMarker :coordinates="[37.588144, 55.733842]" :draggable="true">
<section>
<h1>You can drag this header</h1>
</section>
</YMapMarker>
</YMap>
</div>
</template>
import * as Vue from 'vue';
const [ymaps3Vue] = await Promise.all([ymaps3.import('@yandex/ymaps3-vuefy'), ymaps3.ready]);
export const vuefy = ymaps3Vue.vuefy.bindTo(Vue);
export const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer, YMapMarker} = vuefy.module(ymaps3);
{
"compilerOptions": {
"target": "es2017",
"lib": ["dom", "dom.iterable", "esnext"],
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "node",
"typeRoots": ["./node_modules/@types", "./node_modules/@yandex/ymaps3-types"],
"paths": {
"ymaps3": ["./node_modules/@yandex/ymaps3-types"]
}
}
}
{
"type": "module",
"scripts": {
"dev": "vite"
},
"devDependencies": {
"@yandex/ymaps3-types": "^0.0.27",
"vue": "^3.4.21",
"@vitejs/plugin-vue": "^5.0.4",
"typescript": "^4.9.5",
"vite": "^5.2.8"
}
}
import {defineConfig} from 'vite';
import vue from '@vitejs/plugin-vue';
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
vue: 'vue/dist/vue.esm-bundler.js'
}
}
});
Поставьте зависимости и запустите локальный сервер:
npm install
npm run dev
Откройте приложение
Особенности
-
В теге script, который загружает скомпилированный проектный js, указываем атрибут
type="module"
, чтобы активировать поддержку ECMAScript Modules (ESM) и top-level-await:<script type="module" src="index.ts"></script>
-
В
package.json
добавляем dev-зависимость от пакета@yandex/ymaps3-types
.Рекомендуется устанавливать последнюю версию:
npm i --save-dev @yandex/ymaps3-types@latest
-
В
tsconfig.json
задаёмcompilerOptions.typeRoots
со списком путей к файлам типов. Добавляем туда путь к пакету@yandex/ymaps3-types
, благодаря чему в глобальной области видимости появляется пространство именymaps3
с типами.Примечание
Пространство имен
ymaps3
содержит все типы классов, которые предоставляет JS API, но до резолваymaps3.ready
в среде выполнения они недоступны. -
В
tsconfig.json
задаёмcompilerOptions.paths
, в которой сообщаем ts-компилятору о том, что при импорте пакетаymaps3
его контент следует искать по указанному пути. Благодаря этому в проектных файлах можно импортировать типы словно они лежат не в@yandex/ymaps3-types
, а в пакетеymaps3
:import type {YMapLocationRequest} from 'ymaps3';
Все типы должны быть импортированы из корня.
Внутренняя структура не гарантирована и может меняться со временем.
-
В
tsconfig.json
, для корректной работы top-level-await, параметрcompilerOptions.module
должен быть установлен в одно из следующих значений:es2022
,esnext
,system
илиpreserve
. Также параметрcompilerOptions.target
должен бытьes2017
или выше. -
В
vite.config.ts
задаёмresolve.alias
, чтобы использовать "полную" сборку Vue (vue/dist/vue.esm-bundler.js
). Это необходимо для корректной работыymaps3
Vue компонентов. -
Для каждого объекта в JS API существует аналог Vue. Чтобы использовать версию API Vue, подключите модуль
@yandex/ymaps3-vuefy
. В файлеlib/ymaps.ts
дожидаемся полной загрузки JS API и vuefy модуля, после чего экспортируем необходимые компоненты карты для их использования в других частях проекта:import * as Vue from 'vue'; const [ymaps3Vue] = await Promise.all([ymaps3.import('@yandex/ymaps3-vuefy'), ymaps3.ready]); export const vuefy = ymaps3Vue.vuefy.bindTo(Vue); export const {YMap, YMapDefaultSchemeLayer, YMapDefaultFeaturesLayer} = vuefy.module(ymaps3);
-
Использование top-level-await в
lib/ymaps.ts
гарантирует выполнениеymaps3.ready
иymaps3.import('@yandex/ymaps3-vuefy')
до импорта компонентов карты, что позволяет синхронно использовать любые объекты JS API в качестве компонентов Vue:<YMap :location="LOCATION"> <YMapDefaultSchemeLayer /> <YMapDefaultFeaturesLayer /> ... </YMap>
Указание входных параметров для собственных классов
Компоненты Vue требуют явного объявления входных параметров, чтобы Vue знал, какие из них следует рассматривать как дополнительные атрибуты.
Для базовых объектов из пространства имен ymaps3
входные параметры определены по умолчанию, и никаких дополнительных действий выполнять не требуется.
Если вы разработчик, который создает свои собственные классы (например, в рамках отдельного пакета), то вы можете определить, какие входные параметры будут находиться в компоненте. Определение props поддерживает формат Vue. Например, пользовательский класс YMapSomeClass
:
type YMapSomeClassProps = {
id: string;
counter?: number;
};
export class YMapSomeClass extends ymaps3.YMapComplexEntity<YMapSomeClassProps> {
static [ymaps3Vue.vuefy.optionsKey] = {props: ['id', 'counter']};
//...
}
Помимо массива строк, мы также можем использовать объектный синтаксис:
export class YMapSomeClass extends ymaps3.YMapComplexEntity<YMapSomeClassProps> {
static [ymaps3Vue.vuefy.optionsKey] = {
props: {
id: String,
counter: Number
}
};
//...
}
или с валидацией входных параметров:
export class YMapSomeClass extends ymaps3.YMapComplexEntity<YMapSomeClassProps> {
static [ymaps3Vue.vuefy.optionsKey] = {
props: {
id: {type: String, required: true},
counter: {type: Number, required: false}
}
};
//...
}
Указание входных параметров при использовании сторонних пакетов
Если разработчики сторонних пакетов не определили входные параметры для своих классов, то вы можете указать их самостоятельно при вызове vuefy, передав их в качестве второго аргумента:
const ymaps3Vue = await ymaps3.import('@yandex/ymaps3-vuefy');
const vuefy = ymaps3Vue.vuefy.bindTo(Vue);
const {YMapSomeClass as YMapSomeClassV} = vuefy.module(
{YMapSomeClass},
{
YMapSomeClass: ['id', 'counter'] // props для класса YMapSomeClass
}
);
Аналогичным образом поддерживается синтаксис объекта и валидации, показанные выше.
Пользовательские реализации объектов ymaps3.YMapEntity для Vue
Когда стандартная конвертация недостаточна, используйте overrideKey
ключ чтобы указать свою реализацию для vuefy:
type YMapSomeClassProps = {
id: string;
counter?: number;
};
/* объект ymaps3.YMapEntity */
export class YMapSomeClass extends ymaps3.YMapComplexEntity<YMapSomeClassProps> {
static [ymaps3Vue.vuefy.overrideKey] = YMapSomeClassVuefyOverride;
//...
}
YMapSomeClassVuefyOverride
это метод, который должен вернуть компонент Vue. В качестве параметров он получает базовый класс, объявленные пропсы и объект с Vue и vuefy если потребуются их методы. В примере ниже создается обертка YMapSomeClassV
с дополнительной логикой вокруг компонента, полученным базовым методом vuefy:
export const YMapSomeClassVuefyOverride: CustomVuefyFn<YMapSomeClass> = (
YMapSomeClassI, // базовый YMapSomeClass
props, // объявленные входные параметры
{vuefy, Vue}
) => {
// Стандартный vuefy метод
const YMapSomeClassVuefied = vuefy.entity(YMapSomeClassI, props);
const YMapSomeClassV = Vue.defineComponent({
props,
name: 'YMapSomeClassV',
components: {YMapSomeClassVuefied},
setup() {
// дополнительная логика пользовательской реализации
},
template: `<YMapSomeClassVuefied v-bind="$props" ... />`
});
return YMapSomeClassV;
};
полученный компонент можно использовать в приложении:
const ymaps3Vue = await ymaps3.import('@yandex/ymaps3-vuefy');
const vuefy = ymaps3Vue.vuefy.bindTo(Vue);
const YMapSomeClassV = vuefy.entity(YMapSomeClass);
const app = createApp({
components: {YMapSomeClassV},
template: `<YMapSomeClassV id="some_id" />`
});
app.mount('#app');