2016-06-15 1 views
17

Я сгенерировал проект, используя vue-cli. Я вижу, что в проекте есть один App.vue, который является основным макетом приложения - если я не ошибаюсь. Здесь я разместил свой основной HTML-макет и <router-view></router-view>. Теперь проблема в том, что мне нужен совершенно другой макет для входа (разные обертки, у тела разные классы), но я не могу его изменить, так как у App.vue есть шаблон, который «фиксирован» как макет. Как подойти к этой проблеме? Рекомендуемый способ?vuejs приложение с различными макетами (например, макет входа в систему, макет страницы, регистрация и т. Д.)

Должен ли я создать новый компонент, который представляет собой макет, поэтому в этом случае мой шаблон App.vue будет иметь только <router-view></router-view>, а затем LoginLayout.vue будет включен в него?

ответ

19

Я думаю, что нашел решение. Подход имеет App.vue, содержащий только <router-view></router-view>, а затем включает различные компоненты, которые представляют макет (при необходимости, содержащий <router-view> и подпрограммы). Я нашел проект, используя его таким образом here.

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

+0

Ребенок, как показано в этом связанном проекте, отлично разбирается! – Kong

1

Я не знаю ни о каком «рекомендуемым способом», но мое приложение структурирована следующим образом:

App.vue - только верхняя панель меню (которое не отображается, когда пользователь не прошел проверку подлинности) и <router-view></router-view> для каждого компонента (страница)

Таким образом, каждая страница может иметь совершенно разные макеты.

+0

Это не так просто, шаблон, который у меня есть, совершенно другой по структуре для входа в систему или позволяет использовать панель инструментов - не просто показать скрытые элементы. – user2343398

+1

и это может быть. Весь контент html может быть другим – lukpep

6

Я направляю свои приложения через макет. Например, Логин не требует никакой структуры, только компонента входа в системе, но и другие страницы требуют, колонтитул заголовка и т.д., так вот пример того, как я делаю это в моих маршрутах:

// application routes 
'/secure': { 
    name: 'secure', 
    component: require('../components/layouts/default'), 
    subRoutes: { 
    '/home': { 
     name: 'home', 
     component: require('../components/home/index') 
    } 
    } 
} 

//- public routes 
'/insecure': { 
    name: 'insecure', 
    component: require('../components/layouts/full-bleed'), 
    subRoutes: { 
    '/login': { 
     name: 'login', 
     component: require('../components/session/login') 
    } 
    } 
} 

Оба эти шаблоны компоновки имеет router- так что вы можете создавать свои макеты по мере необходимости для разных частей приложения.

+1

Можете ли вы привести пример этого? –

1

Я динамически проверяю маршрут по всему миру на App.vue и использую его для определения того, что должно отображаться.

App.vue

<template> 
     <div id="app"> 
     <top :show="show" v-if="show.header"></top> 
     <main> 
      <router-view></router-view> 
     </main> 
     <bottom v-if="show.footer"></bottom> 
     </div> 
    </template> 

    <script> 
    export default { 
     mounted: function() { 
     if(window.location.hash == "#/" || window.location.hash.indexOf('route')) { 
      vm.show.header = true 
      vm.show.footer = true 
      vm.show.slideNav = true 
      } 
     } 


     watch: { 
     $route: function() { 
      // Control the Nav when the route changes 
      if(window.location.hash == "#/" || window.location.hash.indexOf('route')) { 
      vm.show.header = true 
      vm.show.footer = true 
      vm.show.slideNav = true 
      } 
     } 
     } 
    } 
    </script> 

Таким образом, я также в состоянии контролировать то, что показано в верхнем и нижнем ЧС через реквизит.

Надеюсь, это поможет!

+0

Это может быть полезно в небольших случаях, но может стать довольно грязным и подверженным ошибкам. –

1

Я знаю, что он старый, но nuxt.js Поддержка в настоящее время. Взгляни.

1

Я нахожу другое решение, используя router meta. Мне просто нужно, чтобы несколько компонентов нуждались в другом макете.

Я добавил plainLayout мета ключ в Src/маршрутизатор/index.js.

export default new Router({ 
    mode: 'history', 
    linkExactActiveClass: 'app-head-menu--active', 
    routes: [ 
    { 
     path: '/', 
     component: Features, 
    }, 
    { 
     path: '/comics/:id', 
     component: Comic, 
     props: true, 
    }, 
    { 
     path: '/comics/:comic_id/:chapter_index', 
     component: Chapter, 
     props: true, 
     meta: { 
     plainLayout: true, 
     }, 
    }, 
    ], 
}); 

Затем делают макет условно с playLayout в SRC/App.vue.

<template> 
    <div> 
    <div v-if="!$route.meta.plainLayout"> 
     <div class="app-head"> 
     </div> 
     <div class="app-content"> 
     <router-view/> 
     </div> 
    </div> 

    <div v-if="$route.meta.plainLayout"> 
     <router-view/> 
    </div> 
    </div> 
</template> 

<script> 
export default { 
    name: 'app', 
}; 
</script> 

Просмотреть демонстрационный проект here.

8

хорошее решение для этого используется slots

Сначала создайте свой "компонент макета"

src/components/layouts/basic.vue

<template> 
    <div class="basic-layout"> 
    <header>[Company logo]</header> 
    <hr> 

    <slot/> 

    <hr> 
    <footer> 
     Made with ❤ at Acme 
    </footer> 
    </div> 
</template> 

Затем использовать его в другом компоненте:

<template> 
    <layout-basic> 
    <p>Hello world!</p> 
    </layout-basic> 
</template> 

<script> 
    import LayoutBasic from '@/components/layouts/basic' 
    export default { 
    components: { 
     LayoutBasic 
    } 
    } 
</script> 

" Hello world "появится, где <slot/> бирка есть.

Вы также можете иметь несколько слотов с именами, см. complete docs.

+0

Это лучшее решение, спасибо вам большое –

+0

Я думаю, что это лучший подход, так как это именно то, для чего предназначены слоты. –

0

Использование маршрутов, и, в частности, детские маршруты - отличный способ приблизиться к общим макетам в Vue.

Все этого кода использует VUE 2.x

Start, имея очень простой компонент VUE под названием App, который не имеет раскладки.

app.vue

<template> 
    <router-view></router-view> 
</template> 

Тогда есть через Routes файл, который вы вернете в экземпляр Вью.

Маршруты (ц | JS).

import Vue from 'vue' 
import VueRouter from 'vue-router' 

const NotFoundComponent =() => import('./components/global/notfound.vue') 
const Login =() => import('./components/account/login.vue') 
const Catalog =() => import('./components/catalog/catalog.vue') 

export default new VueRouter({ 
    mode: 'history', 
    linkActiveClass: 'is-active', 
    routes: [ 
    //Account 
    { path: '/account', component:() => import('./components/account/layout.vue'), 
     children: [ 
      { path: '', component: Login }, 
      { path: 'login', component: Login, alias: '/login' }, 
      { path: 'logout', 
       beforeEnter (to: any, from: any, next: any) { 
        //do logout logic 
        next('/'); 
       } 
      }, 
      { path: 'register', component:() => import('./components/account/register.vue') } 
     ] 
    }, 

    //Catalog (last because want NotFound to use catalog's layout) 
    { path: '/', component:() => import('./components/catalog/layout.vue'), 
     children: [ 
      { path: '', component: Catalog }, 
      { path: 'catalog', component: Catalog }, 
      { path: 'category/:id', component:() => import('./components/catalog/category.vue') }, 
      { path: 'product', component:() => import('./components/catalog/product.vue') }, 
      { path: 'search', component:() => import(`./components/catalog/search.vue`)} , 
      { path: 'basket', component:() => import(`./components/catalog/basket.vue`)} , 
      { path: '*', component: NotFoundComponent }  
     ]  
    }   
    ] 
}) 

код использует отложенную загрузку (с WebPack), так что не позволяйте () => import(...) бросить вас. Это может быть только import(...), если вам нужна активная загрузка.

Важный бит - это маршруты для детей. Таким образом, мы устанавливаем основной путь /account, чтобы использовать /components/account/layout.vue, но тогда самые первые двое детей задают основное содержимое vue (Login). Я решил сделать это так, потому что, если кто-то просто просматривает/account, я хочу приветствовать их с помощью экрана входа в систему. Может быть подходящим для вашего приложения, что/account будет целевой страницей, где они могли бы проверить историю заказов, сменить пароли и т. Д.

Я сделал то же самое для каталога ... / и /catalog оба загружают catalog/layout с файлом /catalog/catalog.

Также обратите внимание, что если вам не нравится идея наличия «подпапок» (например, учетная запись/логин вместо просто/логина), вы можете иметь псевдонимы, как я показываю в логине.

С помощью добавления , alias: '/login' это означает, что пользователи могут просматривать /login, даже если фактический маршрут /account/login.

Это ключ ко всему этому, но только, чтобы попытаться сделать пример полной ...

Вот мой загрузочный файл, который перехватывает мое приложение.вю и маршруты:.

загрузки (TS | JS)

import Vue from 'vue' 
import VueRouter from 'vue-router' 

Vue.use(VueRouter) 

import App from './components/app.vue'; 

import router from './routes'; 

new Vue({ 
    el: '#app', 
    router, 
    render: h => h(App) 
}); 

Я создал layout.vue файл для каждого из моих основных разделов моего приложения (счета, каталог и т.д.).

счет/layout.vue

<template> 
<div> 
    <cc-header></cc-header> 

    <div class="container"> 
     <main> 
      <router-view></router-view> 
     </main> 
     <aside> 
     </aside> 
    </div> 

    <cc-footer></cc-footer>  
</div> 
</template> 

<script lang="ts"> 

import ccHeader from "../common/cc-header.vue" 
import ccFooter from "../common/cc-footer.vue" 

export default { 
    components: { 
     ccHeader, 
     ccFooter 
    } 
} 

</script> 

<style lang="scss" scoped> 

.container { 
    display: flex; 
} 

main { 
    flex: 3; 
    order: 2; 
} 

aside { 
    flex: 1; 
    order: 1; 
} 
</style> 

И макет для каталога ...

каталог/layout.vue

<template> 
<div> 
<cc-header></cc-header> 

<div class="catalog-container"> 
    <main class="catalog"> 
     <router-view></router-view> 
    </main> 
    <cc-categories></cc-categories> 
</div> 

<cc-footer></cc-footer>  
</div> 

</template> 

<script lang="ts"> 
import ccHeader from "../common/cc-header.vue" 
import ccFooter from "../common/cc-footer.vue" 

import ccCategories from "./cc-categories.vue" 

export default { 
    components: { 
     ccCategories, 
     ccHeader, 
     ccFooter 
    }, 
    data : function() : any { 
    return { 
     search: '' 
    }   
}, 
} 
</script> 

<style lang="scss" scoped> 
.catalog-container { 
     display: flex; 
    } 

    .category-nav { 
     flex: 1; 
     order: 1; 
    } 

    .catalog { 
     flex: 3; 
     order: 2; 
    } 
</style> 

Обе макеты используют общие компоненты, такие как верхний и нижний колонтитулы, но им это не нужно. В макете каталога есть категории в боковой навигационной панели, а в макете учетных записей нет. Я поместил свои общие компоненты под компоненты/общие.

общий/footer.vue

<template> 
<div> 
    <hr /> 
    <footer> 
     <div class="footer-copyright"> 
      <div>© Copyright {{year}} GlobalCove Technologies, LLC</div> 
      <div>All rights reserved. Powered by CoveCommerce.</div> 
     </div> 
    </footer> 
</div> 
</template> 

<script lang="ts"> 
    import Vue from "vue"; 
    export default Vue.component('cc-footer', { 

     data : function() : any { 
     return { 
      year: new Date().getFullYear() 
     }   
    }, 
    }) 

</script> 

<style lang="scss"> 
</style> 

Общая структура файла

src/ 
    boot.ts 
    routes.ts 

    components/ 
     app.vue 

     catalog/ 
      layout.vue 
      catalog.vue 
      category.vue 
      product.vue 
      search.vue 
      basket.vue 

     account/ 
      layout.vue 
      login.vue 
      register.vue 

     global/ 
      notfound.vue 

     common/ 
      cc-header.vue 
      cc-footer.vue    

Сочетание маршрутов, простой app.vue и отдельных файлов макета, наряду с общими компонентами должны получить вы, где вы хотите быть.

Смежные вопросы