Компоненты динамического макета Vue.js
предисловие
- Vue.js — это прогрессивно улучшенная библиотека представлений, которую можно использовать как часть страницы .html или в сочетании с vue-router, vuex и axios для создания одностраничных или многостраничных приложений. Взяв за пример разработку одной страницы, в процессе разработки разные страницы должны использовать разные макеты страниц.Далее мы рассмотрим различные способы работы с макетами в Vue.js.
- Создайте приложение Vue на базе Vue Router (основная структура ниже), оно отлично работает. (Но допустим, есть процесс оформления заказа, в котором вы не хотите показывать навигацию. Или у вас могут быть страницы продуктов с боковыми панелями и другие страницы без боковых панелей и т. д.) Столкнувшись с таким разнообразием требований, что мы делаем, чтобы удовлетворить Что? о сохранении кода в сопровождении и легком расширении при сохранении бизнес-требований? Давайте обсудим вместе.
<template>
<div class="App">
<nav class="App__nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
<footer>
© Awesome Company
</footer>
</div>
</template>
Метод реализации
- Условный рендеринг: самый простой и простой подход — условно отображать определенные части макета. Таким образом, вы можете добавлять директивы v-if к определенным частям вашего макета и переключать видимость по мере необходимости.
<template>
<div class="App">
<nav v-if="showNav" class="App__nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<router-view/>
<footer v-if="showFooter">
© Awesome Company
</footer>
</div>
</template>
- Объяснение: одна из проблем с этим подходом заключается в том, что вам нужно контролировать видимость определенных элементов в вашем приложении, обрабатывая глобальное состояние в Vue.js. Хотя это может быть правильным подходом, если вам не нужны очень сложные макеты и вы просто хотите скрыть определенные элементы в определенных контекстах, этот подход может стать кошмаром для обслуживания по мере роста вашего приложения.
- Статический компонент-оболочка макета: используйте обычный компонент (содержащий один или несколько слотов для разных частей макета) в качестве оболочки для представления, он обеспечивает большую гибкость и не кажется таким грязным, как подход условного рендеринга.
// app.vue
<template>
<div class="App">
<router-view/>
</div>
</template>
// LayoutDefault.vue
<template>
<div class="LayoutDefault">
<nav class="LayoutDefault__nav">
<router-link to="/">Home</router-link> |
<router-link to="/about">About</router-link>
</nav>
<main class="LayoutDefault__main">
<slot/>
</main>
<footer class="LayoutDefault__footer">
© Awesome Company
</footer>
</div>
</template
// home.vue
<template>
<layout-default>
<div class="Home">
<h1>Home</h1>
<p>
Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
amet.
</p>
<h2>Amet sit</h2>
<p>
Eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
amet.
</p>
</div>
</layout-default>
</template>
<script>
import LayoutDefault from '../layouts/LayoutDefault.vue';
export default {
name: 'Home',
components: {
LayoutDefault,
},
};
</script>
- проиллюстрировать:
- Компонент Home.vue реализует компонент-оболочку LayoutDefault для переноса своего содержимого.
- Хотя в этом подходе есть все, что нам нужно с точки зрения гибкости, упаковка наших представлений в компонент статического макета имеет огромный недостаток: компонент уничтожается и создается заново каждый раз при изменении маршрута.
- Это не только негативно влияет на производительность, поскольку клиент должен заново создавать компонент макета (и все другие компоненты, вложенные в него) снова и снова при каждом изменении маршрута, но также означает, что вам нужно извлекать некоторые данные при каждом изменении пути, которое вы используете. в компоненте макета.
- Компоненты-оболочки статического макета очень мощные и гибкие, но они также имеют свою стоимость. Давайте посмотрим вместе, если мы сможем придумать метод, обладающий всеми положительными свойствами статического компонента-оболочки, но ни один из отрицательных, то это лучшее решение.
- Компонент-оболочка динамического макета
- Прежде чем мы начнем, давайте представим очень мощный динамический компонент системы компонентов в Vue.js.
<component :is="SomeComponent"/>
- В приведенном выше примере SomeComponent — это переменная, которая может быть динамически назначена любому компоненту, и каждый раз, когда назначается другой компонент, шаблон будет отображать новый компонент там, где вы определяете разметку.
- Мы можем использовать динамические компоненты для создания очень гибкой и производительной системы динамической компоновки. код показывает, как показано ниже:
// app.vue
<template>
<component :is="layout">
<router-view :layout.sync="layout"/>
</component>
</template>
<script>
export default {
name: 'App',
data() {
return {
layout: 'div',
};
},
};
</script>
// home.vue
<template>
<div class="Home">
<h1>Home</h1>
<!-- ... -->
</div>
</template>
<script>
import LayoutDefault from '../layouts/LayoutDefault.vue';
export default {
name: 'Home',
created() {
this.$emit('update:layout', LayoutDefault);
},
};
</script>
- Выше вы можете видеть, что мы больше не оборачиваем шаблон представления макета в компонент LayoutDefault, а загружаем компонент и выдаем его как новое значение свойства макета, которое мы определили в базовом компоненте приложения. Это означает, что как только компонент Home будет создан, динамический компонент, обертывающий визуализированный компонент Home, будет повторно визуализирован для рендеринга компонента, который мы выпустили в хуке created().
- Почему это лучше, чем статический компонент-оболочка? Основное отличие состоит в том, что компонент компоновки не является частью компонента представления маршрутизатора, а оборачивает его. Это означает, что компонент макета ==повторно отображается== только в том случае, если компонент представления использует макет, отличный от предыдущего компонента представления.
- Продолжайте рефакторить код, чтобы сделать использование динамического макета более интуитивно понятным.
// 修改home.vue
<template>
<layout name="LayoutDefault">
<div class="Home">
<h1>Home</h1>
<!-- ... -->
</div>
</layout>
</template>
<script>
import Layout from '../layouts/Layout';
export default {
name: 'Home',
components: {
Layout,
},
};
</script>
// src/layouts/Layout.js
import Vue from 'vue';
export default {
name: 'Layout',
props: {
name: {
type: String,
required: true,
},
},
created() {
// Check if the layout component
// has already been registered.
if (!Vue.options.components[this.name]) {
Vue.component(
this.name,
() => import(`../layouts/${this.name}.vue`),
);
}
this.$parent.$emit('update:layout', this.name);
},
render() {
return this.$slots.default[0];
},
};
<templat