Progressive Enhancement (прогрессивное улучшение) — подход к разработке веб-приложений, при котором базовая функциональность доступна всем пользователям, а расширенные возможности включаются по мере поддержки современных браузеров и устройств. Во Vue.js этот принцип применяется через постепенное усложнение компонентов и логики без ущерба для доступности и производительности.
Ключевой аспект — отделение структуры HTML от динамического поведения. Базовая HTML-разметка должна быть полностью функциональной и читабельной без Jav * aScript:
<ul>
<li>Элемент 1</li>
<li>Элемент 2</li>
<li>Элемент 3</li>
</ul>
Vue.js позволяет постепенно усиливать взаимодействие с помощью директив:
<ul id="app">
<li v-for="item in items" :key="item.id">{{ item.name }}</li>
</ul>
const app = Vue.createApp({
data() {
return {
items: [
{ id: 1, name: 'Элемент 1' },
{ id: 2, name: 'Элемент 2' },
{ id: 3, name: 'Элемент 3' },
]
}
}
});
app.mount('#app');
Браузеры без поддержки JavaScript покажут статический HTML, а включенный Vue добавляет динамическое поведение без нарушения базовой функциональности.
Vue.js строится вокруг компонентов, что идеально подходит для Progressive Enhancement. Компоненты обеспечивают инкапсуляцию состояния и поведения, что позволяет постепенно добавлять интерактивность.
Пример базового компонента:
app.component('todo-item', {
props: ['todo'],
template: `<li>{{ todo.text }}</li>`
});
Использование компонента:
<ul>
<todo-item v-for="item INTOdos" :key="item.id" :todo="item"></todo-item>
</ul>
Базовый HTML может существовать независимо, а Vue добавляет интерактивные свойства и реактивность. При необходимости можно расширить компонент, добавив обработку событий и анимацию:
app.component('todo-item', {
props: ['todo'],
template: `
<li @click="toggleDone" :class="{ done: todo.done }">
{{ todo.text }}
</li>
`,
methods: {
toggleDone() {
this.todo.done = !this.todo.done;
}
}
});
Vue предоставляет набор встроенных директив, которые позволяют поэтапно улучшать элементы страницы:
v-if и v-else — условное отображение;v-show — скрытие и отображение без удаления DOM;v-for — циклы по массивам и объектам;v-bind — динамическое связывание атрибутов;v-on — обработка событий.Пример прогрессивного улучшения:
<button v-on:click="increment" :disabled="!enabled">
Нажми меня
</button>
data() {
return {
count: 0,
enabled: true
};
},
methods: {
increment() {
this.count++;
}
}
Если JavaScript отключен, кнопка просто отображается статически, не ломая функциональность страницы.
Reactivity в Vue.js позволяет автоматически обновлять интерфейс при изменении данных. Для Progressive Enhancement важно, чтобы данные были доступны в HTML при первой загрузке:
<ul>
<li v-for="post in posts">{{ post.title }}</li>
</ul>
data() {
return {
posts: [] // базовые данные можно подгрузить через серверный рендеринг
};
},
mounted() {
fetch('/api/posts')
.then(response => response.json())
.then(data => this.posts = data);
}
Первоначально сервер может рендерить HTML с базовыми элементами. После подключения Vue данные обновляются динамически, улучшая взаимодействие без потери доступности.
Vue поддерживает SSR (Server-Side Rendering), что идеально соответствует принципам Progressive Enhancement. Сервер формирует HTML, который сразу доступен пользователю, а Vue подключается на стороне клиента для добавления интерактивности:
import { createSSRApp } from 'vue';
import App from './App.vue';
export function createApp() {
const app = createSSRApp(App);
return { app };
}
Это обеспечивает максимальную доступность и быстрый First Contentful Paint, даже если клиентский JavaScript загружается медленно или отключен.
Слоты (<slot>) позволяют вставлять базовый контент
в компонент, который может быть расширен при подключении Vue:
<modal>
<p>Базовое сообщение</p>
</modal>
app.component('modal', {
template: `
<div class="modal">
<slot></slot>
<button @click="$emit('close')">Закрыть</button>
</div>
`
});
Базовый контент доступен без скриптов, а Vue добавляет обработку событий и динамические элементы.
Для больших приложений Progressive Enhancement включает поэтапную загрузку компонентов. Vue поддерживает динамический импорт:
const AsyncComponent = defineAsyncComponent(() =>
import('./HeavyComponent.vue')
);
Это позволяет пользователю взаимодействовать с основной функциональностью сразу, а дополнительные возможности загружаются только по необходимости.
Формы должны быть полностью функциональны без JavaScript, но Vue может улучшить их интерактивность:
<form @submit.prevent="handleSubmit">
<input type="text" v-model="name" required>
<button type="submit">Отправить</button>
</form>
data() {
return { name: '' };
},
methods: {
handleSubmit() {
alert(`Привет, ${this.name}`);
}
}
Если JavaScript отключен, форма отправляется стандартным HTTP-запросом, сохраняя базовую функциональность.
Progressive Enhancement во Vue.js обеспечивает надежную и доступную основу для разработки, позволяя строить динамичные, отзывчивые интерфейсы без потери базовой функциональности.