В этом материале речь пойдёт о том, как перевести проект, созданный с использованием jQuery, на Vue.js. Этот проект будет создан на jQuery, а потом переработан с применением Vue. Автор материала хочет продемонстрировать всем желающим то, что использование Vue, даже в сравнительно небольших проектах, не обязательно означает чрезмерное увеличение размера кода таких проектов и большую дополнительную нагрузку на программиста. Это, наоборот, при практически тех же размерах вспомогательного кода, что и при использовании jQuery, позволяет повысить производительность труда и улучшить качество приложений.
Обзор проекта
Мы собираемся разработать простой электронный счёт, основанный на этом опенсорсном шаблоне от Sparksuite.
Нередко в подобных учебных примерах используют всяческие списки дел. Надеюсь, отступление от этой традиции сделает рассказ свежее и интереснее, и, при этом, наша задача окажется достаточно сложной для того, чтобы на её примере можно было продемонстрировать преимущества использования чего-то вроде Vue для разработки небольших проектов. Руководство построено так, чтобы все желающие без особых сложностей могли бы его воспроизвести и освоить предлагаемые методы работы.
Вот шаблон счёта, с которым мы хотим поработать.
Электронный счёт
Мы собираемся добавить ему интерактивных возможностей, сделав так, чтобы в нём можно было бы выбирать товар, его количество и цену за единицу. При изменении значений будет пересчитываться итоговая стоимость товара и общая сумма по документу. Кроме того, мы добавим сюда кнопку, которая позволит вставлять в счёт новые пустые строки.
Я модифицировал шаблон, приведя HTML-код пустой строки к следующему виду:
<tr class="item">
<td><input value="" /></td>
<td>$<input type="number" value="0" /></td>
<td><input type="number" value="1" /></td>
<td>$0.00</td>
</tr>
Разработка проекта на jQuery
Для начала посмотрим на то, как решить нашу задачу с использованием jQuery.
$('table').on('mouseup keyup', 'input[type=number]', calculateTotals);
Мы подключаем прослушиватель событий к таблице. Этот прослушиватель вызовет функцию
calculateTotals
при изменении значений, соответствующих стоимости единицы товара или его количеству:function calculateTotals() {
const subtotals = $('.item').map((idx, val) => calculateSubtotal(val)).get();
const total = subtotals.reduce((a, v) => a + Number(v), 0);
$('.total td:eq(1)').text(formatAsCurrency(total));
}
Функция берёт строки таблицы и проходится по ним, передавая каждую из строк функции
calculateSubtotal
и суммируя результаты. Результат вычислений попадает в константу total
. В итоге общая сумма по документу подставляется в соответствующее поле счёта.function calculateSubtotal(row) {
const $row = $(row);
const inputs = $row.find('input');
const subtotal = inputs[1].value * inputs[2].value;
$row.find('td:last').text(formatAsCurrency(subtotal));
return subtotal;
}
В этом коде мы берём ссылки на все поля
<input>
, присутствующие в строке, затем умножаем значения, хранящиеся во втором и третьем полях для получения значения subtotal
. Потом это значение вставляется в последнюю ячейку строки. Мы форматируем это значение с помощью функции formatAsCurrency
. Вот её код:function formatAsCurrency(amount) {
return `$${Number(amount).toFixed(2)}`;
}
Кроме того, у нас имеется небольшая вспомогательная функция, которую мы используем для того, чтобы обеспечить одинаковый внешний вид полей с суммами по товарам и по документу в целом. А именно, нам надо, чтобы перед числами, находящимися в этих полях, стоял знак $, и чтобы они представляли собой десятичные числа с двумя знаками после запятой.
$('.btn-add-row').on('click', () => {
const $lastRow = $('.item:last');
const $newRow = $lastRow.clone();
$newRow.find('input').val('');
$newRow.find('td:last').text('$0.00');
$newRow.insertAfter($lastRow);
$newRow.find('input:first').focus();
});
И, наконец, у нас имеется обработчик события нажатия на кнопку
Add row
, которая служит для добавления в документ новой строки. Здесь мы берём последнюю строку в таблице, содержащую данные о товаре, и делаем её копию. При этом в поля этой новой строки мы вставляем стандартные данные. Кроме того, мы можем тут позаботиться об удобстве работы пользователя и установить фокус на первое поле новой строки, что позволит пользователю, сразу же после добавления новой строки, приступить к вводу данных в её первое поле.Вот рабочий пример счёта, интерактивные возможности которого реализованы средствами jQuery.
Недостатки решения, основанного на jQuery
Зададимся вопросом о том, каковы недостатки вышеописанного подхода, или, скорее, вопросом о том, как улучшить наш проект.
Возможно, вы слышали о новых библиотеках, вроде Vue и React, о которых говорят, что они позволяют работать в декларативном, а не в императивном стиле. Если посмотреть на вышеприведённый jQuery-код, ясно, что он, в основном, читается как набор инструкций, описывающих манипуляции с DOM. Цель каждого раздела этого кода, то есть, ответ на вопрос о том, что он делает, часто довольно сложно выяснить, глядя на то, как он это делает. Конечно, можно сделать намерения используемых фрагментов кода яснее, разбив его на функции с вдумчиво подобранными именами. Однако если оставить этот код на какое-то время, а потом опять к нему вернуться, окажется, что для того, чтобы его понять, всё равно придётся приложить некоторые усилия.
Ещё одна проблема подобного кода заключается в том, что состояние приложения хранится в DOM. Информация о товарах, которые хочет заказать пользователь, существует лишь как часть HTML-разметки в пользовательском интерфейсе. Если всё, что нам надо — это выводить данные в одном месте, то эта проблема не кажется такой уж серьёзной. Однако, как только появляется необходимость выводить эти данные в нескольких местах приложения, перед нами возникает задача синхронизации данных. Не имея, как в нашем случае, единого источника достоверных данных, очень сложно поддерживать их в актуальном состоянии во всём приложении.
Хотя при использовании jQuery ничто не мешает нам хранить состояние приложения за пределами DOM и избежать вышеописанной проблемы, библиотеки, такие как Vue, предоставляют возможности, которые способствуют созданию приложений, обладающих хорошей архитектурой. Эти библиотеки помогают программисту писать более чистый и лучше структурированный код.
Перевод проекта на Vue
Теперь поговорим о том, как воссоздать тот же функционал на Vue. Для того чтобы воспользоваться возможностями Vue, достаточно просто подключить эту библиотеку к обычной веб-странице, так же, как это делается в случае с jQuery. То есть, нет необходимости пользоваться системой для упаковки модулей или транспилятором, не нужно разбивать приложение на компоненты и раскладывать их код по .vue-файлам.
Начнём перевод проекта на Vue с замены содержимого тега
<script>
:<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
На следующем шаге надо создать новый экземпляр Vue:
const app = new Vue({
el: 'table'
});
Единственным параметром, который надо передать конструктору нового экземпляра Vue, является
el
. Это — селектор (такой же, какими пользуются и в jQuery), который идентифицирует ту часть документа, которой мы хотим управлять с помощью Vue.Vue можно поручить задачи разного масштаба — от управления целой страницей (в случае, например, с одностраничным приложением), до небольшого фрагмента, заключённого в тег
<div>
. В нашем примере Vue будет отвечать за работу с HTML-таблицей.Данные
Добавим в экземпляр Vue условные данные для трёх строк документа:
const app = new Vue({
el: 'table',
data: {
items: [
{ description: 'Website design', quantity: 1, price: 300 },
{ description: 'Hosting (3 months)', quantity: 1, price: 75 },
{ description: 'Domain name (1 year)', quantity: 1, price: 10 },
]
}
});
Свойство
data
— это то место, где мы храним состояние приложения. Состояние включает не только данные, с которыми должно работать наше приложение, но и информацию о состоянии пользовательского интерфейса (например — о том, какой из разделов приложения, состоящего из нескольких вкладок, активен в настоящий момент, или о том, свёрнут ли некий виджет, вроде «аккордеона», или развёрнут).Vue способствует тому, чтобы состояние приложения было бы отделено от его представления (то есть, от DOM), и помогает централизованно хранить состояние в одном месте, которое является единым источником достоверных данных.
Модификация шаблона
Теперь настроим шаблон таким образом, чтобы он выводил данные, хранящиеся в объекте
data
. Так как мы сообщили фреймворку о том, что хотим, с помощью экземпляра Vue, работать с таблицей, мы можем использовать синтаксис шаблонов Vue в HTML-коде, описывающем эту таблицу для того, чтобы сообщить Vue о том, как визуализировать таблицу и как с ней работать.Используя атрибут
v-for
, мы можем вывести блок HTML-кода для каждого элемента из массива items
:<tr class="item" v-for="item in items">
</tr>
Vue повторит эту разметку для каждого элемента массива (или объекта), который передаётся
v-for
. Это позволяет нам обратиться к каждому элементу в цикле. В данном случае этот элемент представлен переменной item
. Так как Vue наблюдает за свойствами объекта data
, фреймворк будет динамически обновлять разметку при изменении содержимого массива items
. Всё, что нам надо сделать — это модифицировать состояние, добавив или удалив элементы, а Vue будет автоматически обновлять пользовательский интерфейс.Нам, кроме того, надо добавить поля ввода, которые мог бы заполнять пользователь, вводя описание товара, цену за единицу, количество:
<td><input v-model="item.description" /></td>
<td>$<input type="number" v-model="item.price" /></td>
<td><input type="number" v-model="item.quantity" /></td>
<td>${{ item.price * item.quantity }}</td>
Здесь мы используем атрибут
v-model
для того, чтобы настроить двустороннюю привязку данных между полями ввода и свойствами в модели данных. Это означает, что изменение данных в полях ввода приведёт к их изменению в модели, и наоборот.В последней ячейке мы используем фигурные скобки
{{}}
, их мы применяем для вывода текста. В скобках можно использовать любое рабочее JavaScript-выражение. В данном случае мы умножаем два свойства элемента и выводим то, что получилось. Опять же, Vue наблюдает за моделью данных, изменение любого свойства приведёт к автоматическому пересчёту выражения.События и методы
Теперь у нас имеется шаблон, готовый к выводу коллекции
items
и перед нами возникает вопрос о том, как добавлять в таблицу новые строки. Так как Vue выведет на страницу всё, что имеется в массиве items
, для того, чтобы вывести на страницу пустую строку, достаточно передать Vue объект с любыми значениями, которые должны присутствовать в массиве items
.Для того чтобы создать функцию, к которой можно обращаться из шаблона, нужно передать эту функцию экземпляру Vue как свойство объекта
methods
:const app = new Vue({
// ...
methods: {
myMethod() {}
},
// ...
})
Объявим метод
addRow
, который можно будет вызывать для добавления нового элемента в массив items
:methods: {
addRow() {
this.items.push({ description: '', quantity: 1, price: 0 });
},
},
Обратите внимание на то, что любые создаваемые нами методы будут автоматически привязаны к экземпляру Vue, что даст нам возможность обращаться из этих методов к свойствам объекта
data
и к другим методам как к свойствам this
.Итак, метод теперь у нас есть. Как его вызывать по нажатию кнопки
Add row
? Для добавления прослушивателей событий к элементам управления в шаблоне в Vue используется синтаксическая конструкция v-on:event-name
.<button class="btn-add-row" @click="addRow">Add row</button>
В Vue, кроме того, предусмотрено сокращение для конструкции
v-on
:, которое выглядит как @
. Оно использовано в вышеприведённом фрагменте кода. В качестве обработчика события можно использовать любой метод из экземпляра Vue.Вычисляемые свойства
Теперь нам осталось лишь вывести общую сумму по документу в нижней части счёта. Это вполне можно сделать в самом шаблоне. Как уже было сказано, Vue позволяет размещать в конструкциях из фигурных скобок любые рабочие JS-выражения. Однако гораздо лучше придерживаться подхода, при котором в шаблоне хранят только очень простую логику и ничего больше. Если логика будет отделена от шаблона, код окажется чище, его будет легче тестировать.
Для этой цели мы можем использовать обычный метод, но я полагаю, что в данном случае нам лучше всего подойдёт так называемое вычисляемое свойство. Работа с такими свойствами напоминает вышеописанную работу с методами. А именно, для создания таких свойств экземпляру Vue передают объект
computed
, содержащий функции, результаты выполнения которых мы хотим использовать в шаблоне:const app = new Vue({
// ...
computed: {
total() {
return this.items.reduce((acc, item) => acc + (item.price * item.quantity), 0);
}
}
});
Теперь на вычисляемое свойство можно сослаться из шаблона:
<tr class="total">
<td colspan="3"></td>
<td>Total: ${{ total }}</td>
Как вы уже могли заметить, с вычисляемыми свойствами в шаблоне работают так, как будто они являются данными. «Вызывать» что либо в шаблоне при этом не нужно. У использования вычисляемых свойств есть и другое преимущество. Vue — система достаточно интеллектуальная, она кэширует возвращённые значения и пересчитывает их только в том случае, если меняются свойства, от которых зависят значения вычисляемых свойств.
Если бы мы использовали метод для подсчёта общей суммы по документу, вычисления выполнялись бы каждый раз при выводе шаблона. Но, так как мы используем вычисляемое свойство, общая сумма пересчитывается только при изменении значений
quantity
или price
в строках таблицы.Фильтры
Возможно вы заметили, что в реализации нашего проекта, созданной с использованием Vue, есть одна небольшая ошибка. Она заключается в том, что когда цены отдельных товаров выражены целыми числами, вычисленные значения итоговых сумм по строкам и общей суммы по документу выводятся в виде целых долларовых значений, без центов. Нам хотелось бы, чтобы, как и в примере, сделанном на jQuery, в этих числах всегда присутствовали два числа после запятой.
Вместо того, чтобы модифицировать код, ответственный за вычисление итогового значения по строке, и код, вычисляющий общую сумму по документу, мы можем воспользоваться удобными возможностями Vue по форматированию данных. Речь идёт о фильтрах.
Как вы уже, наверное, поняли, для того, чтобы создать фильтр, достаточно передать экземпляру Vue объект (
filters
в данном случае) с соответствующим ключом:const app = new Vue({
// ...
filters: {
currency(value) {
return value.toFixed(2);
}
}
});
Здесь мы создали очень простой фильтр, который называется
currency
. Он вызывает функцию toFixed(2)
для переданного ему числового значения и возвращает полученный результат. Использовать этот фильтр в шаблоне можно так:<td>Total: ${{ total | currency }}</td>
Вот готовая реализация нашего проекта на Vue.
Итоги
Если сравнить две версии проекта, одну — созданную с использованием jQuery, вторую — написанную на Vue, можно заметить следующие сильные стороны приложения, основанного на Vue:
- Чёткое разделение между пользовательским интерфейсом, логикой и данными, управляющими интерфейсом. Код получился более понятным, его будет легче тестировать.
- Декларативное описание интерфейса. Программисту надо позаботиться лишь о том, как описать то что ему хочется видеть на экране, а не о том, как обратиться к DOM для того, чтобы придать странице приложения нужный внешний вид.
Библиотеки Vue и jQuery имеют почти одинаковый размер (в килобайтах). Конечно, размер jQuery можно уменьшить, благодаря использованию собственной сборки библиотеки, но, даже в сравнительно простых проектах, таких, как наш пример электронного счёта, полагаю, простота разработки и читабельность кода оправдывают некоторое увеличение размера приложения.
Кроме того, возможности Vue гораздо шире тех, что мы здесь описали. Сила этого фреймворка заключается в том, что он позволяет создавать модульные, подходящие для повторного использования компоненты пользовательского интерфейса, из которых можно строить сложные клиентские приложения.
Если тема разработки веб-приложений на Vue вам интересна — взгляните на этот материал. Кроме того, если вы подумываете о переводе проектов с чистого JS на Vue — вот наша недавняя публикация на эту тему.
Уважаемые читатели! Пользуетесь ли вы jQuery? И, если пользуетесь, планируете ли менять эту библиотеку на что-то другое, например — на Vue?
Комментарии (39)
Splo1ter
14.06.2018 14:51-3Зачем эта статья? Практической ценности у нее ноль.
Лучше открыть документацию по Vue и все.vvzvlad
14.06.2018 16:00Тем более, что у vue есть хорошая документация на русском языке: ru.vuejs.org/v2/guide/index.html
fapsi
14.06.2018 15:59Вот готовая реализация нашего проекта на Vue
И в Item все 3 пункта — «Website design». Это фича Vue или m-r Nilson Jacques не доглядел?
Madeas
14.06.2018 16:18Я все чаще встречаю в сети упоминания про Vue и его использование. Отсюда два итога:
1. Vuе вытеснит некоторые из используемых библиотек/фреймворков полностью
2. Vue как и прочие фреймворки просто займет свою нишу и будет использоваться среди n-тысяч разработчиков. Остальные тысячи будут работать как и раньше
Мне, как человеку, начавшему изучать js пока не ясно, куда двигаться потом… Вот и во что лучше верить?)SaturnTeam
14.06.2018 17:28Я бы с вами поспорил начиная с выводов. Частое упоминание, с вашей точки зрения не означает, что для всех vue тоже часто упоминается, и уж тем более это не означает что vue закрепится и займет стойкую нишу. до vue часто упоминали CoffeScript и ActionScript, и широко использовали. Теперь же они канули в лету.
Лично я верю и делаю ставку на Angular, так как за ним стоит гугл, и то, как движется эта платформа (ага, даже не фреймворк, а именно платформа) внушает веру в счастливый мир фронтенд разработки как на бекенде. Я верю что он задавит vue и несоклько позже — react. но это лишь мое мнение.nexus478
15.06.2018 00:00Еще есть пункт 3 — WebAssembly (лет через 5 наверное). Но скорее всего этого срока хватит, чтобы выйти раньше, чем какой-то JS-фреймворк станет монополистом.
neurocore
15.06.2018 06:29Нет, vue не вытеснит, скорее займёт какую-то долю среди фреймов. Как человеку, начавшему изучать js, советую вам продолжить его изучением именно vue.js. Он прост в понимании, не требует особой подготовки. Этот опыт в последствии существенно облегчит переход на любой другой фреймворк, если потребуется.
Не в качестве рекламы, а обучения для
www.youtube.com/watch?v=NtlVno8igVQ
мне очень понравились эти лекции — ёмко, коротко и по делу.
nemilya
14.06.2018 17:02Спасибо за перевод. Хорошая статья для начинающих, на практическом примере jQuery и Vue — чтобы сориентироваться в основах.
Единственно замечание: "Нередко в подобных учебных примерах используют всяческие списки дел." — тут "списки дел" мне кажется можно смело заменить на "ToDo")
SergeRod
14.06.2018 21:46Этот замечательный и нестандартный пример довольно прост. Давайте усложним задачу. Добавим условие, что заказчик чудесного приложения-инвойса требует, чтобы приложение было расширяемое путем добавления внешних модулей, без пересборки основного кода приложения. Ну, например, добавлением дополнительных скриптов в html код. С целью дополнения основного функционала — показ отдельной строчкой "налог с продаж" или, там, добавление колонки "единица измерения".
На jQ такое реализуется довольно просто и создание таких дополнений не вызовет трудностей. У Vue добавление дополнительных свойств в модель, инспекторов, методов уже после создания объекта приложения — дело куда более затратное, насколько я понимаю.
justboris
15.06.2018 09:50Расширяемые компоненты можно сделать на любом фреймворке, хоть на vanilla.js. Получится такое API:
// создаем таблицу const table = new InvoiceTable(); // расширяемся table.addColumn(...);
Что там под капотом и какой фреймворк используется — неважно. Какие именно преимущества здесь дает jQuery?
RSalo
14.06.2018 21:46-2глупое сравнение. жикуэри — удобная либа, а вуе — удобная вьюшка.
предположим, что у нас есть какой-то список, который нужно как-то отсортировать. нам проще по быструхе заюзать жикуэри, чем подгружать отдельные данные на страницу и потом уже из них в самом вуе формировать список
KeyJoo
14.06.2018 22:50Пусть будет здоровая конкуренция среди либ/фреймвоков, и коммьюнити — дружелюбным. Мир меняется и вэб тоже(технологии).
maxfox
14.06.2018 23:28Vue — это замечательно, но в той части, где про недостатки jQuery (почему не Vanilla JS?), все выглядит так, будто для хранения состояния нам обязательно нужна либа/фреймворк. Но это не правда, состояние может быть обычным js объектом, а отображение в html — обычной функцией. Такое решение будет весьма компактным и при этом хорошо структурированным, разобраться в нем не составит труда. Если интерфейс становится сложнее, то можно использовать Redux, к примеру. Да и Vue — не единственное решение, Preact, к примеру, весит всего 3kb, отличный вариант для встраивания в классические, не-SPA сайты.
Fess_blaga
15.06.2018 09:38+1Но это не правда, состояние может быть обычным js объектом, а отображение в html — обычной функцией.
Следующим шагом добавим в объект состояния get и set на каждое свойство, чтобы отслеживать изменения и реактивно менять отображение, и через n-ное количество улучшений напишем свой Vue))maxfox
15.06.2018 21:16Ну, мне больше Redux нравится… Но речь не об этом, а о том, что если вам нужно сделать одну форму, или еще что-нибудь такое же простое, то можно обойтись безо всяких библиотек. Просто возьмите основную идею — глобальное состояние, которое отображается в html разметку или в наличие/остутствие определенных классов у определенных DOM элементов.
remeder
15.06.2018 09:38На отсутствие фокуса на инпуте вновь добавленной строки во Vue версии, как я понимаю, даже автор не счел нужным заострить внимание.
Fess_blaga
15.06.2018 09:54+1Кстати, да.
Хотя сделать это можно буквально в несколько строчек.
Vue.directive('focus', { inserted: function (el, binding) { if (binding.value) { el.focus() } } }) //......... methods: { addRow() { this.items.push({ description: "", quantity: 1, price: 0, focus: true }); } },
<tr class="item" v-for="item in items"> <td><input v-model="item.description" v-focus="item.focus" /></td> <td>$<input type="number" v-model="item.price" /></td> <td><input type="number" v-model="item.quantity" /></td> <td>${{ item.price * item.quantity | currency }}</td> </tr>
agentx001
15.06.2018 13:12Ну прекратите вы уже сравнивать JQuery с фреймворками для SPA! Достоинства первого — это тысячи различных плагинов на любой цвет и вкус — колорпикеры, календари, слайдеры, кроперы картинок и все такое. Конкретно данный пример вообще не показывает преимущества Vue, все тоже самое можно за пол часа на ваниле сделать. Ну серьезно, кто-то в 2018 году пользуется джикверей ради манипуляций с DOM?
ht-pro
15.06.2018 15:01Почему все делают мануалы на самые банальные вещи, которые легко осваиваются через документацию?
Почему бы не сделать более интересные руководства, например, что лучше использовать при отправке AJAX-запросов, как обрабатывать отправленные данные на сервере и возвращать их и т.д.
ИМХО, сегодня это было бы более полезно.
Magister7
У решения на Vue есть недостаток, который тут не упомянули: при отключённом Javascript пользователь не увидит ничего, в то время как с решением на jQuery — данные будут, но потеряется редактирование.
neurocore
Кто-то отключает js в 2018 году?
Magister7
Встречал в интернете таких.
Ну а если скрипт загружается со стороннего ресурса — то и я такое через uMatrix блокирую у себя, разрешаю только выборочно.
Вобщем, вопрос в ЦА конкретной задачи. Лендинг, например, с использованием Vue я бы не стал делать.
Madeas
Сейчас куда ни плюнь, попадешь в лендинг)
EskakDolar
Как раз в 2018 году стал отключать js на некоторых сайтах.
Майнеры оборзели, да и без майнинга сайты иногда завешаны скриптами как новогодние елки игрушками.
KeyJoo
А как узнать, что на сайте развели майнинг ферму?
EskakDolar
Не знаю как другие, я чисто по интуиции. Если броузер конкретно тормозит пока JS не отключишь на этом сайте то тут два варианта, либо майнеры, либо то с яндексдирект переборщили. Только, по моему, яндексдирект в последнее время стал чем то вроде майнинга.
walkman7
`Shift + Esc` в хроме (и хром подобных) открывает диспетчер вкладок, там и смотришь на аномальную загрузку ЦП.
YakovSS
Наверное самое просто нагрузкой на цп, хотя бывают хитрецы и делают ее совсем небольшой
justboris
Конечно, если иногда болит голова, то надо отрезать ее насовсем.
Про то что майнеры распространяются с конкретных доменов, которые можно добавить в блеклист — нет, не слышали.
EskakDolar
Не корректное сравнение.
На совсем никакой «головы» я не отрезаю.
Отключаю и включаю JS по необходимости.
Про блеклист в который Роскомнадзор уже два месяца помещает Телеграм я слышал.
myrrec
Например, я. Зачем сайту, на котором располагается какая-то информация, js? Для анимации перелистывания статей/переходов к верху страницы/гугл-аналитики/скриптов наподобие jivosite? Без этого вполне можно обойтись.
Так что для сайтов, которыми пользуюсь каждый день, js включен, остальное режется NoScript-ом.
cyberly
Ну… иногда при блокировании некоторых мессенджеров временно не работают некоторые CDN. Форс-мажор, но тем не менее…
Fedcomp
Скорее проблема с точки зрения поисковых систем.
lllypynby
Прекрптите вводить людей в заблуждение, уже всё работает.
Fedcomp
И яндекс и гугл поддерживают страницы с динамическим содержимым?
evocatus
Гугл is generally able (т.е. когда как, но в общем да), а Яндекс — однозначно нет.
TheShock
Fedcomp
Суть в том, что с jquery, изза того что оно как правило имеет начальный html — таких проблем нет. А то что все эти фреймворки стоит объединять с SSR в статье ни слова. И то что это резко становится не просто «заменить jquery на раз два».
TheShock