Вы когда-нибудь испытывали страх оставить позади свои любимые библиотеки JS, стоит ли включать Dart в свой стек разработчика? Что ж, не бойтесь больше, потому что команда Dart предоставила средства для включения ваших любимых библиотек JavaScript!

Решение представлено в виде пакета js, который предоставляет прокси для вызова методов JavaScript API. В этой статье мы рассмотрим несколько примеров с объектом window и реальный пример с jQuery.

Вот исходный код, содержащий решение.

Продолжить чтение в моем блоге

Предварительное условие

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

mkdir new_project && cd new_project
stagehand web-simple

Добавьте следующее в pubspec.yaml под зависимостями:

dependencies:
  js: ^0.6.0

И запустите pub get. Также убедитесь, что у вас установлено webdev (pub global activate webdev)

Теперь мы готовы перейти к примерам!

Пример с объектом window

При установке пакета js аннотация @JS() используется как средство доступа к API JavaScript на объекте хоста window.

Вот фрагмент, который можно использовать в web/main.dart для вызова window.console.log():

@JS() // sets the context, in this case being `window`
library main; // required library declaration
import 'package:js/js.dart'; // Pull in our dependency
@JS('console.log') // annotates `log` function to call `console.log`
external void log(dynamic str);
void main() {
  log('Hello world!'); // invokes console.log() in JavaScript land
}

Запустите webdev serve и посетите URL-адрес localhost, чтобы увидеть результат. Чтобы увидеть обновления, просто сохраните файл и перезагрузите страницу.

Аннотированный файл должен начинаться с объявления библиотеки, которая также имеет аннотацию @JS(), которую мы видим в строках 1–2. Поскольку первая аннотация не имеет аргументов, она устанавливает контекст других аннотаций относительно глобального объекта window. Таким образом, переход к этой строке @JS('console.log') описывает переход от window к свойству console, имеющему метод log.

Вот еще один пример установки контекста на window.console:

@JS('console') // Our `console` namespace
library main; // library name can be whatever you want
import 'package:js/js.dart';
@JS('log') // Setting the proxy to the `console.log` method
external void log(dynamic str);
void main() {
  log('Hello world!');
}

Поскольку файл начинается с пространства имен console, следующая аннотация для метода log исключает префикс console. Ключевое слово external для метода log используется для обозначения этого метода вне Dart, иначе ожидается тело функции. Кроме того, поскольку наша функция названа с тем же именем, что и метод на console, мы можем полностью удалить указанную выше аннотацию.

// @JS('log') // remove
external void log(dynamic str);

Обратите внимание: вам не нужен этот пакет взаимодействия, если вам нужен только доступ к встроенным свойствам на window. Для этого используйте dart:html библиотеку Дарта. Приведенный выше фрагмент предназначен только для иллюстрации, поэтому пакет js может использоваться при использовании внешних библиотек.

Реальный пример с jQuery

Чтобы использовать jQuery, давайте импортируем его в web/index.html перед тегом скрипта, запрашивающим main.dart.js:

<script defer src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Теперь создайте файл с именем web/jquery.dart, содержащий приведенный ниже фрагмент:

@JS()
library jquery;
import 'package:js/js.dart';
// new jQuery invokes JavaScript `new jQuery()`
@JS()
class jQuery {
  external factory jQuery(String selector);
  external int get length; // we get this from jQuery instance
}

Давайте проведем рефакторинг main.dart, чтобы проверить это:

import './jquery.dart';
void main() {
  print(jQuery('#output')); // [object Object]
  print(jQuery('#output').length); // 1
}

Давайте сделаем что-нибудь более интригующее, используя методы css() и animate():

@JS()
class jQuery {
  external factory jQuery(String selector);
  external int get length;
  external jQuery css(Map options);
  external jQuery animate(Map options);
}

Вызов обоих методов вернет экземпляр jQuery так же, как и API на основе JS.

Теперь это не сработает должным образом, поскольку options параметры ожидают тип Map. Мы не можем передать объект Dart Map, потому что он «непрозрачен» в JavaScript. Другими словами, вы получите объект, не содержащий того, что вы ожидаете.

Чтобы это заработало, нам нужно определить конструктор фабрики с ключами, которые нам понадобятся:

@JS()
@anonymous // needed along with factory constructor
class CssOptions {
  external factory CssOptions({ backgroundColor, height, position, width });
  external String get backgroundColor;
  external String get position;
  external num get height;
  external num get width;
}

И измените объявление внешнего метода css() следующим образом:

external jQuery css(CssOptions options);

Сделаем то же самое для метода animate:

@JS()
@anonymous
class AnimateOptions {
  external factory AnimateOptions({ left, top });
  external dynamic get left;
  external dynamic get top;
}

И измените объявление внешнего метода animate() следующим образом:

external jQuery animate(AnimateOptions options);

Теперь мы можем вызывать наши методы в web/main.dart как таковые:

import './jquery.dart';
void main() {
  jQuery('#output')
    .css(CssOptions(
      backgroundColor: 'green',
      height: 100,
      position: 'relative',
      width: 100))
    .animate(AnimateOptions(left: 100, top: 100));
}

И ожидайте результата ниже:

Заключение

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

Это решение работает для любой библиотеки JavaScript, имеющей пространство имен под объектом window, что охватывает 99% случаев.

Как всегда, я надеюсь, что это было проницательно, и вы узнали что-то новое сегодня. И вот суть полного решения.

дальнейшее чтение

  1. пакет js в пабе
  2. Vue.js – Начало работы в Dart
  3. Бесплатные скринкасты по Dart на Egghead.io

Делиться заботой 🤗

Если вам понравилось читать эту статью, поделитесь ею в различных социальных сетях. Кроме того, проверьте и подписывайтесь на мой канал YouTube (также нажмите значок колокольчика) для видео на Dart.

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

Поставьте лайк, поделитесь и подписывайтесь на меня 😍, чтобы узнать больше о Dart.