Графоманские пояснения к тому как можно не запариться используя vue вместо extjs.

Пока салаты не остыли решил написать пояснение с примером к предыдущему посту. Так как меня не совсем верно поняли (оно и понятно, я совсем не писатель). Сейчас я попытаюсь пройтись по основным пунктам, с картинками и пояснением к ним, на примере уже существующего компонента (кому лень читать конечный результат в конце). Внимание будет попахивать агитацией и пропагандой!
В общем погнали.

(можно скипнуть) Честно говоря изначально я хотел написать простенький компонент с нуля, но ничего более или менее полезного мне в голову не пришло. По этому как коннектить modx и vue покажу на примере этого компонента. Из описания: «Компонент позволяет блокировать как отдельно взятый ip так и его узлы. Если вы используете Formit совместно с хуком FormItSaveForm, то можно банить прямо от туда.». Я его делал для личных нужд, в репозитории его нет, но если хотите можете сбилдить и выложить. Компонент представляет из себя кастомный (с немного расширенной таблицей) modExtra и написан с участием extjs. В интерфейсе нет ничего необычного, основные элементы это грид и модальное окошко. Давайте попробуем избавиться от extjs и посмотрим что у нас получиться.

(шаг один) И так мои действия:
  1. Клонируем git clone https://github.com/srsad/BanOnIP.git в корень и получаем вот такую классическую структуру

    Думаю она в пояснении не нуждается, это чистый MODX с папкой компонента BanOnIP в корне.
  2. Выполняем билд перейдя по адресуhttp://tmp.loc/BanOnIp/_build/build.php. Теперь в админке появился новый пункт BanOnIp.

  3. Переходим в раздел «Пространство имен» /manager/?a=workspaces/namespace и меняем птуть к ядру и адрес активов, чтоб можно было работать из папки BanOnIP

  4. Теперь удаляем всё из /BanOnIp/assets/components/banonip/js/mgr/
Если сейчас попробовать открыть страницу с компонентом, то мы ничего не увидим =) и это не удивительно, мыж только что весь интерфейс удалили.

(шаг два) Подключаем vue.
  1. если у вас не установлен vue cli 3, то ставим через npm или yarn npm install -g @vue/cli или yarn global add @vue/cli (при этом у вас должна стоять свежая nodejs), а если установлен, то в папке с проектом выполняем команду vue create --preset srsad/vue-modx-preset . терминале, ждем, ждем, ждем и по итогу получаем такой результат:

    Как видим папка немного разрослась, но бояться не стоит. (кстати папку public со всем содержимым удаляем)
  2. Открываем BanOnIp/core/components/banonip/controllers/home.class.php и делаем такое:
    public function initialize()
    {
        $this->BanOnIP = $this->modx->getService('BanOnIP', 'BanOnIP', MODX_BASE_PATH . 'BanOnIP/core/components/banonip/model/');
        #$this->BanOnIP = $this->modx->getService('BanOnIP', 'BanOnIP', MODX_CORE_PATH . 'components/banonip/model/');
        parent::initialize();
    }
    Тут особо нечего комментировать…
    public function loadCustomCssJs()
    {
        $this->addCss('../BanOnIP/assets/components/banonip/css/mgr/main.css');
        $this->addJavascript('../BanOnIP/assets/components/banonip/js/mgr/dist/app.js');
        $this->addHtml('<script type="text/javascript">
            var BanOnIP = {
                connector_url: "' . $this->BanOnIP->config['connectorUrl'] . '",
                modAuth: "' . $this->modx->user->getUserToken($this->modx->context->get('key')) . '",
            };
        </script>');
    }
    И копируем id div`а banonip-panel-home-div.
  3. Идем в папку src => App.vue меняем id в блоке template и script:
    <template>
      <div id="banonip-panel-home-div">
            <!-- предварительно удаляем hello world -->
      </div>
    </template>
    
    <script>
    export default {
      name: 'banonip-panel-home-div',
      components: {
    
      }
    }
    </script>
  4. Теперь открываем main.js и подключаем начальные данные для старта работ:
    import Vue from 'vue'
    import App from './App.vue'
    import axios from 'axios'
    import VueAxios from 'vue-axios'
    import vueModx from 'vuemodx'
    
    import './assets/main.sass'
    
    Vue.config.productionTip = false
    
    window.onload = function() {
    	Vue.use(VueAxios, axios)
    	Vue.use(vueModx, {
    		lexicon: MODx.lang, // Обратите внимание сюда, ниже я подробней опишу этот момент
    		appId: 'banonip-panel-home-div'
    	});
    
    	Vue.prototype.$httpConfig = {headers: {'modAuth': BanOnIP.modAuth}};
    
    	new Vue({
    		render: h => h(App),
    	}).$mount('#banonip-panel-home-div');
    };
    В предыдущей статье я описывал немного иную конструкцию для работы с лексиконами из vue и там я упомянул, что не придумал способа лучше, чем передавать словарик через объект компонента. Так вот, оказывается есть переменная MODx.lang которая содержит в себе все необходимое!
  5. Теперь можно запустить vue в режиме build --mode development, как я описывал во втором шаге предыдущей стати
Чтож на этом все, можно поместить в App.vue => data, что нибудь типа message: 'hello ' и оно будет отрабатывать в админке.

Конечный результат выглядит так (gif`ка):


Посмотреть можно тут, НО это далеко не эталон, я в прямом смысле накидал макет по быстрому.
Так как это пример коннекта vue и MODX, то некоторые моменты я опустил. Если быть точнее, то я не реализовал поиск, сортировку по столбцам и контекстное меню. Но этого и не требовалось, главное чтоб вы поняли принцип!

Людям которые всегда хотели использовать что-то новое, но почему то тянули, я настоятельно советую перейти по этой ссылке и потыкать хотяб минут 30 (предупреждаю в документации время летит не заметно).

Перечислю еще немного преимуществ вдогонку к предыдущему посту:
— Он совместим с чем угодно, можно даже jquery плагины к нему присабачить и они будут работать как родные.
— Можно работать без вебпака или cli, например его можно подключить через cdn, <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script>, собрать быстрое решение а потом просто вернуться и сделать как надо! Тут главное вернуться =(
— Огромное количество готовых решений, которые каждый день пополняются. Если не нашел варианта который удовлетворяет на 100%, то возможность реализовать собственный плагин а затем просто переиспользовать.
— vue конечно достаточно молодой, но в тоже время не совсем юный, чтоб можно было опасаться его кончины. Вообще насколько я знаю (сильно не вникал), но Эван Ю сейчас работает не один а с командой, плюс он поучает неплохой доход с патреона. Все эти факторы говорят о том, что в ближайшие годы vue точно будет на волне, по этому можно не бояться его использовать.
— всегда свежая и очень хорошая документация на русском и английском языке (не баян а классика). Из-за этого пункта, можно начать использовать базовые возможность vue прямо в день знакомства. Т.е. документация настолько структурирована и хороша, что вам может показаться это простой игрой. Открыл главу, почитал немного теории, потыкал по кнопам, вник, поэкспериментировал немного и открыл следующую главу.

P.S. Решил таки собрать маленький и удобный modExtra-cli, который позволит собрать рабочее окружение с пол пинка минуя всю процедуру которую я выше описывал. Начал я это дело буквально сегодня и пока он может принимать и обрабатывать команды, качать исходный modExta и переименовывать (пока тестирую) чтоб можно было не запускать лишний раз rename.php, имеем вот такой базовый набросок (gif`ка):

Суть его такова:
1) Пишем имя создаваемого компонента
2) Выбираем инструмент с которым будем работать (vue или классический extjs), если выбрали vue, то он должен докачать данные, раскидать в нужные места и подредактировать при необходимости home.php
3-5) Эти пункты можно скипнуть, они связанны автоматическим переименованием, указанием авторства и с выбором лицензии.
После этого cli сам загрузит и настроит окружение, нужно бутет только выполнить build.php и на время разработки сменить путь к ядру и активам в разделе «Пространства имён».

Ближайшие планы такие:
— Нужно собрать файл с кастомными стилями к различным элементам вроде таблиц, инпутов, селектов и т.д., всем кто хочт помочь с этим делом могут отправлять свои решения пулреквестом (линк пока не дам) или просто кидайте мне ссылку на codepen-подобные сервисы и я все перенесу сам (с миру по нитке).
— Сделать несколько базовых плагинов на vue для использования в админке, те-же таблицы, возможно контекстное меню, селекты, дерево ресурсов/папок ну и т.д… На этом пока все.
P.P.S. Сейчас 2 часа ночи, по этому надеюсь что ничего не забыл…
srs
srs
02 января 2019, 02:07
6
788
+22

Комментарии: 25

Вася
03 января 2019, 14:46
+3
Отставлю комментарий
Просто нехорошо, что у такого интересного поста ни одного комментария: )
    srs
    srs
    03 января 2019, 15:18
    +3
    Спасибо)
    Но вообще я сам виноват, не лучшее время подобрал, может после праздников будет по больше активности. Да и людям далеким от vue, все таки это не совсем близко.
Павел Голубев
03 января 2019, 23:31
0
Пробовал подружить ExtJS и Vue.

Наткнулся на vuetifyjs.com/, но его гриды — это слезы в сравнении с тем, что может ExtJS 10 летней давности. Ну и когда пытаешься впилить стили от vuetifyjs вся админка расползается.
    srs
    srs
    04 января 2019, 11:09
    +1
    Так гриды есть не только у vuetify, не нравиться одно, используй другое решение. А как вы впиливайте стили? Vue можно применять стили изолированно, чтоб не было конфликтов.
    Кстати говоря о гридах, гриды у extjs действительно не плохи, основные его преимущества:
    1. Можно подключить сортировку
    2. Можно перетаскивать колонки
    3. Есть контекстное меню
    4. Есть построчная навигация из коробки
    Но это вполне стандартный набор который можно реализовать самому или найти готовое решение. В любом случае у меня в планах есть сборка аналога грида под vue.
    Вообще vuetify это отдельный UI, я не пробовал втиснуть в админку целый UI. Честно говоря я и необходимости такой никогда не видел. Но вечером ради интереса потыкаю.
    srs
    srs
    04 января 2019, 12:33
    0
    В общем запустил, проверил! У меня только стрелочки в дереве ресурсов чуть выше сместились и поле поиска стало чуть компактнее, на этом все! НО! Стоит понимать, что вы использовали готовый UI набор, стоит понимать что он скорее всего будет перекрывать родные стили. Я не ходок в Material Design, но думаю, что там можно изолированно подключать не весь набор стилей, например отдельно таблицы, отдельно навигацию и т.д.
    В общем вот как это выглядит у меня, без подключенных иконок.

    P.S. А чего вам конкретно не хватает в таблицах от Material Design? Просто судя по вашему комментарию там все ну очень плохо!
    P.P.S. Кстати у него и подход другой, он подгружает все данные и разбивает на страницы, т.е. например сортировка происходит не по запросу в бд а прямо в массиве. В extjs все иначе и на мой взгляд правильней, там мы подгружаем часть данных а любые дополнительные действия (например сортировка или поиск) идут через запросы к бд, В примере я кстати именно так и реализовывал.
      Павел Голубев
      04 января 2019, 13:13
      1
      +1
      А чего вам конкретно не хватает в таблицах от Material Design? Просто судя по вашему комментарию там все ну очень плохо!
      — кастомного рендеринга колонок
      — грида в гриде
      — коллапс тулс
      — менеджера колонок, чтобы можно было скрывать нужные/ненужные в данный момент
      — сортировок на бэкенде
      — инлайн-редактирования + виджеты для инлайн-редактирования
      — группового редактирования данных

      Гриды — сложная штука. Если глянуть в Github www.ag-grid.com/ github.com/ag-grid/ag-grid/issues?q=is%3Aissue+is%3Aclosed то ужасаешься сколько всего нужно запилить, чтобы получить рабочий продукт.
        srs
        srs
        04 января 2019, 14:05
        0
        — коллапс тулс — если я вас правильно понял
        — сортировок на бэкенде — я тоже об этом упоминал, но был не прав, на той-же странице есть пункт «Разбиение на страницы и сортировка на стороне сервера»
        — инлайн-редактирования + виджеты для инлайн-редактирования — нашел минимальны пример, пункт «Встроенное редактирование»
        — группового редактирования данных — пункт «Выбираемые строки»
        — менеджера колонок который позволяет скрыть нужные/ненужные колонки, достаточно быстро прикрутить, хотя возможно это уже есть и нужно лучше изучить документацию. Только давайте мы с вами тут этого делать не будем=)
        Ничоси пример)! Тот грид который сейчас в modx конечно навороченный, но он явно не свариться с ag-grid.
Владимир
04 января 2019, 16:37
0
По п.3 у меня не работает поле Путь к активам. Все что не пропишу в этом поле все равно используется корневая директория assets, даже если оставить поле пустое или заполнить несуществующим путем. В чем здесь может быть проблема?
    srs
    srs
    04 января 2019, 17:52
    +2
    Проблема в том, что нужно так-же произвести настройки в файле home.class.php (второй шаг, пункт 2). Прошу прощенья, для меня это тоже «проба пера», наверное нужно было как нибудь «слить» эти моменты=)
    Вообще я рекомендую немного повременить с этим делом, я в процессе написания cli который поможет миновать все эти шаги (готовность ~70%). Если срочных дел не выскочит, то через 2-3 для кину линк в комментариях или в этом посте.
Алексей
05 января 2019, 10:06
0
А есть ли способ использовать vue для TV-параметров?
    srs
    srs
    05 января 2019, 11:57
    +1
    Пока плотно на эту тему не думал, по этому точного рецепта, да и рецепта в целом, пока дать не могу. Но вполне возможно, через некоторое время напишу маленькую заметку с примерами на подобную тему.
      Алексей
      05 января 2019, 12:16
      0
      а если вкратце — появилась возможность используя стандартные процессоры modx'а (для вывода таблички к примеру, её сортировки и постраничной навигации) отказаться от extjs и отрисовывать табличку на vue? т.е. меняется только Фреймворк javascript, ну а весь бэкэнд php-шный остается тем же самым. Всё ли верно? -)
        Руслан Сафин
        05 января 2019, 12:31
        +1
        В принципе верно.
        php отдает json потом axios, vue

        Дерево, список шаблонов, тв и т.д. в vuex хранить можно, шустро работать будет все… Осталось найти тех кто перенесет все с extJs на Vue js =)))
          srs
          srs
          05 января 2019, 17:51
          +1
          Тут проблема в том, что ТВшки можно использовать n+1 количество раз в одном документе. А vue привязывается к конкретному id. Т.е. если вызвать разово, то вроде как проблем нет… но если попытаться вызвать более одной копии, то полетят матюки. Я на вскидку представляю как можно решить эту проблему, но это костыль и нужно изучать глубже этот вопрос. В любом случае в ближайшее время мне нужно будет ковырять в эту сторону, но пока ничем помочь не могу.
          Кстати, есть запрос от одного клиента на pageBuilder для MODX, так что возможно через пару месяцев вы увидите Гутендерг для бедных. Если у людей будет интерес, то я могу расписать процесс в виде пары статей.
          А вот про перенос всего с extjs на vue, то давайте будет реалистами ;). Вообще стоит подождать дайджест от Ивана, может он расскажет нам интересностей о будущем MODX и когда планируется уход в полноценное API для взаимодействия с системой.
            Василий Наумкин
            05 января 2019, 19:36
            0
            А vue привязывается к конкретному id
            Как-то же Ext умудряется генерировать случайные id и потом с ними работать?

            Но проблема не в этом — все типы ТВ инициализируются на ExtJS, как встроенные, так и кастомные. нынешние ТВ — это вообще по сути своей такой костыль спец-код, который расширяет именно ExtJS страницу ресурса.

            Так что для Vue нужно писать новые кастомные типы ТВ.
              srs
              srs
              06 января 2019, 02:34
              0
              Да, только extjs не нужно потом компилировать, а vue нужно явно указывать с чем он может работать и за пределами этой области он абсолютно бесполезен. Как вариант можно вешать привязку vue на глобальный id (например modx-content), и оттуда генерировать столько тв`шек сколько влезит. Но скорее всего это плохая идея и можно сделать все правильно =)
                Василий Наумкин
                06 января 2019, 08:10
                +1
                Его ж можно и без template вызывать, по-простому. В случае с ТВшками это будет кастомный тип с примерно такой инициализацией:
                var tvX = new Vue({
                  el: id_from_php,
                  data: json_data_from_php
                })
                  srs
                  srs
                  06 января 2019, 14:50
                  0
                  Семён Семёныч!!! Действительно, тогда вообще проблем нет никаких.
          Василий Наумкин
          05 января 2019, 19:34
          0
          Там в PHP сейчас просто дофига Ext-специфичных вещей.

          Именно поэтому все говорят о написании отдельного нового REST API, но делать это для 2.х никому не интересно. Так что, ждём движений в MODX 3.
Андрей Степаненко
05 января 2019, 21:52
+3
Vue — аху… нен. Знаю по себе писал интернет-магазин на vue js + minishop2 через API с поддержкой сессий store и других фич vue: platon.site

Ну вот как сессиями работать в MODx Vue?
Там получается сперва надо написать middleware который будет перекрывать какой то код который будет сперва инициализировать либо тянуть данные на ajax.

Даже взять простую функцию: запоминание табов (то есть оставатся на табе который выбран) это не постоешь без того что выше.
    srs
    srs
    06 января 2019, 02:56
    0
    Ну вот как сессиями работать в MODx Vue?
    Там получается сперва надо написать middleware который будет перекрывать какой то код который будет сперва инициализировать либо тянуть данные на ajax.
    Честно говоря я такой связки еще не делал, но мне альтернативы вашей идее как-то в голову не приходит. Да и скорее всего это наиболее верный подход. Можно этот вопрос задать в чате vue или nuxt, там как минимум накидают различных вариантов которые можно будет более пристально изучить. А вот касаемо табов то можно и на куку повесить)
    Знаю по себе писал интернет-магазин на vue js + minishop2 через API с поддержкой сессий store и других фич vue: platon.site
    Вот об этом былоб очень интересно почитать! Яб даже финансовую благодарочку дал.
Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.