Use vue components as one-offs in layout scaffolding

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












I've recently been getting into VueJS and CSS Grid. In the past I've always used frameworks like Bootstrap to built up my layout. However, since CSS Grids and VueJS have caught my attention, I'm trying to build a responsive layout using both.



My question now is, can (or should) one generally use vue components for the basic layout? I've built an off-canvas navigation for smaller viewpoints and turned it into a vue component:



hamburger.vue:



<template>
<div class="hamburger">
<div class="bar" :class=" 'bar-top' : this.text "></div>
<div class="bar" :class=" 'bar-middle' : this.text "></div>
<div class="bar" :class=" 'bar-bottom' : this.text "></div>
</div>
</template>

<script>
export default
props: ['text']

</script>

<style lang="scss" scoped>
@import "../../../sass/core/_variables";

.hamburger
position: absolute;
right: 15px;
top: 15px;
display: block;
cursor: pointer;
transition: transform .7s ease-in-out;

@media only screen and (min-width: $tablet)
display: none;


.bar
width: 30px;
height: 4px;
margin-bottom: 5px;
background-color: #000000;
border-radius: 3px;
transition: all .7s ease;

.bar:last-child
margin-bottom: 0px;

.bar-top
transform: translateY(9px) rotateZ(45deg);

.bar-middle
opacity: 0;

.bar-bottom
transform: translateY(-10px) rotateZ(-45deg);

</style>


And I am including it in my main layout like so:



<div id="root">
<header role="banner" :class=" 'nav-open' : mobile ">
<div class="container">
<h2>Header</h2>
<hamburger :text="mobile" @click.native="mobile = !mobile"> </hamburger>
</div>
<section class="hero is-dark is-bold">
<div class="hero-body">
<div class="container">
<h1 class="title">Hero title</h1>
<h2 class="subtitle">Hero subtitle</h2>
</div>
</div>
</section>
</header>
<nav role="navigation" :class=" 'nav-open' : mobile ">
<div class="container">
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<li>Item 4</li>
<li>Item 5</li>
<li>Item 6</li>
</ul>
</div>
</nav>
<section id="main" :class=" 'nav-open' : mobile ">
<main role="main">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
</main>
<aside>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim.</p>
</aside>
</section>
<footer role="footer" :class=" 'nav-open' : mobile ">
<div class="container">
<h2>Footer</h2>
</div>
</footer>
</div>


So the way it works is, on my vue instance I set mobile = false, then by clicking the hamburger I can toggle it and therefore transition the off-canvas nav in.



navigation.scss:



@media only screen and (min-width: $tablet) 
ul
display: grid;
grid-template-columns: repeat(auto-fit, minmax(100px, auto));
> li
margin: 0 auto;


.toggle
display: none;



@media only screen and (max-width: $tablet - 1px)
nav
position: fixed;
top: 0;
bottom: 0;
width: $nav;
right: -$nav;

nav,
header,
section#main,
footer
transition: transform .7s ease-in-out;

.nav-open
transform: translateX(-$nav);




My main layout.scss:



/*! Mobile View */

#root
display: grid;
grid-template-columns: 1fr;


/*! Desktop View */

#root > section #main
margin: 0 auto;
@media only screen and (min-width: $tablet)
display: grid;
grid-column-gap: 20px;
grid-template-columns: repeat(10, 1fr);
main
grid-column: span 7;

aside
grid-column: span 3;


@media only screen and (min-width: $desktop)
width: 90%;




Obviously this is just scaffolding. In the end I'm not sure about 3 things:



  • Should I keep the mobile / off-canvas navigation as a vue component, or incorporate in my layout scss files? I did it because because this way all the styling, JavaScript and HTML is contained in a single file. On the other hand, the way I learned it, one should create a component if one wants to reuse a particular piece of code more than once, which I'm obviously not doing here. I'm only using it once. Is it still viable (also in terms of performance)?


  • One thing I'm unsure about is :class=" 'nav-open' : mobile " in my markup. The way I build it I have repeat it several times in my markup (once for sliding in the off-canvas nav, but also three times for sliding out (to the right) the header, main section and footer). It's repetitive, but I don't know if it can be done better.


  • Would you have setup the Grid similarly using CSS Grid, or should I change something? I was trying to scaffold it with mobile-first in mind, while being as minimal / performant as possible.







share|improve this question



























    up vote
    3
    down vote

    favorite












    I've recently been getting into VueJS and CSS Grid. In the past I've always used frameworks like Bootstrap to built up my layout. However, since CSS Grids and VueJS have caught my attention, I'm trying to build a responsive layout using both.



    My question now is, can (or should) one generally use vue components for the basic layout? I've built an off-canvas navigation for smaller viewpoints and turned it into a vue component:



    hamburger.vue:



    <template>
    <div class="hamburger">
    <div class="bar" :class=" 'bar-top' : this.text "></div>
    <div class="bar" :class=" 'bar-middle' : this.text "></div>
    <div class="bar" :class=" 'bar-bottom' : this.text "></div>
    </div>
    </template>

    <script>
    export default
    props: ['text']

    </script>

    <style lang="scss" scoped>
    @import "../../../sass/core/_variables";

    .hamburger
    position: absolute;
    right: 15px;
    top: 15px;
    display: block;
    cursor: pointer;
    transition: transform .7s ease-in-out;

    @media only screen and (min-width: $tablet)
    display: none;


    .bar
    width: 30px;
    height: 4px;
    margin-bottom: 5px;
    background-color: #000000;
    border-radius: 3px;
    transition: all .7s ease;

    .bar:last-child
    margin-bottom: 0px;

    .bar-top
    transform: translateY(9px) rotateZ(45deg);

    .bar-middle
    opacity: 0;

    .bar-bottom
    transform: translateY(-10px) rotateZ(-45deg);

    </style>


    And I am including it in my main layout like so:



    <div id="root">
    <header role="banner" :class=" 'nav-open' : mobile ">
    <div class="container">
    <h2>Header</h2>
    <hamburger :text="mobile" @click.native="mobile = !mobile"> </hamburger>
    </div>
    <section class="hero is-dark is-bold">
    <div class="hero-body">
    <div class="container">
    <h1 class="title">Hero title</h1>
    <h2 class="subtitle">Hero subtitle</h2>
    </div>
    </div>
    </section>
    </header>
    <nav role="navigation" :class=" 'nav-open' : mobile ">
    <div class="container">
    <ul>
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
    <li>Item 4</li>
    <li>Item 5</li>
    <li>Item 6</li>
    </ul>
    </div>
    </nav>
    <section id="main" :class=" 'nav-open' : mobile ">
    <main role="main">
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
    </main>
    <aside>
    <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim.</p>
    </aside>
    </section>
    <footer role="footer" :class=" 'nav-open' : mobile ">
    <div class="container">
    <h2>Footer</h2>
    </div>
    </footer>
    </div>


    So the way it works is, on my vue instance I set mobile = false, then by clicking the hamburger I can toggle it and therefore transition the off-canvas nav in.



    navigation.scss:



    @media only screen and (min-width: $tablet) 
    ul
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, auto));
    > li
    margin: 0 auto;


    .toggle
    display: none;



    @media only screen and (max-width: $tablet - 1px)
    nav
    position: fixed;
    top: 0;
    bottom: 0;
    width: $nav;
    right: -$nav;

    nav,
    header,
    section#main,
    footer
    transition: transform .7s ease-in-out;

    .nav-open
    transform: translateX(-$nav);




    My main layout.scss:



    /*! Mobile View */

    #root
    display: grid;
    grid-template-columns: 1fr;


    /*! Desktop View */

    #root > section #main
    margin: 0 auto;
    @media only screen and (min-width: $tablet)
    display: grid;
    grid-column-gap: 20px;
    grid-template-columns: repeat(10, 1fr);
    main
    grid-column: span 7;

    aside
    grid-column: span 3;


    @media only screen and (min-width: $desktop)
    width: 90%;




    Obviously this is just scaffolding. In the end I'm not sure about 3 things:



    • Should I keep the mobile / off-canvas navigation as a vue component, or incorporate in my layout scss files? I did it because because this way all the styling, JavaScript and HTML is contained in a single file. On the other hand, the way I learned it, one should create a component if one wants to reuse a particular piece of code more than once, which I'm obviously not doing here. I'm only using it once. Is it still viable (also in terms of performance)?


    • One thing I'm unsure about is :class=" 'nav-open' : mobile " in my markup. The way I build it I have repeat it several times in my markup (once for sliding in the off-canvas nav, but also three times for sliding out (to the right) the header, main section and footer). It's repetitive, but I don't know if it can be done better.


    • Would you have setup the Grid similarly using CSS Grid, or should I change something? I was trying to scaffold it with mobile-first in mind, while being as minimal / performant as possible.







    share|improve this question























      up vote
      3
      down vote

      favorite









      up vote
      3
      down vote

      favorite











      I've recently been getting into VueJS and CSS Grid. In the past I've always used frameworks like Bootstrap to built up my layout. However, since CSS Grids and VueJS have caught my attention, I'm trying to build a responsive layout using both.



      My question now is, can (or should) one generally use vue components for the basic layout? I've built an off-canvas navigation for smaller viewpoints and turned it into a vue component:



      hamburger.vue:



      <template>
      <div class="hamburger">
      <div class="bar" :class=" 'bar-top' : this.text "></div>
      <div class="bar" :class=" 'bar-middle' : this.text "></div>
      <div class="bar" :class=" 'bar-bottom' : this.text "></div>
      </div>
      </template>

      <script>
      export default
      props: ['text']

      </script>

      <style lang="scss" scoped>
      @import "../../../sass/core/_variables";

      .hamburger
      position: absolute;
      right: 15px;
      top: 15px;
      display: block;
      cursor: pointer;
      transition: transform .7s ease-in-out;

      @media only screen and (min-width: $tablet)
      display: none;


      .bar
      width: 30px;
      height: 4px;
      margin-bottom: 5px;
      background-color: #000000;
      border-radius: 3px;
      transition: all .7s ease;

      .bar:last-child
      margin-bottom: 0px;

      .bar-top
      transform: translateY(9px) rotateZ(45deg);

      .bar-middle
      opacity: 0;

      .bar-bottom
      transform: translateY(-10px) rotateZ(-45deg);

      </style>


      And I am including it in my main layout like so:



      <div id="root">
      <header role="banner" :class=" 'nav-open' : mobile ">
      <div class="container">
      <h2>Header</h2>
      <hamburger :text="mobile" @click.native="mobile = !mobile"> </hamburger>
      </div>
      <section class="hero is-dark is-bold">
      <div class="hero-body">
      <div class="container">
      <h1 class="title">Hero title</h1>
      <h2 class="subtitle">Hero subtitle</h2>
      </div>
      </div>
      </section>
      </header>
      <nav role="navigation" :class=" 'nav-open' : mobile ">
      <div class="container">
      <ul>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
      <li>Item 4</li>
      <li>Item 5</li>
      <li>Item 6</li>
      </ul>
      </div>
      </nav>
      <section id="main" :class=" 'nav-open' : mobile ">
      <main role="main">
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
      </main>
      <aside>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim.</p>
      </aside>
      </section>
      <footer role="footer" :class=" 'nav-open' : mobile ">
      <div class="container">
      <h2>Footer</h2>
      </div>
      </footer>
      </div>


      So the way it works is, on my vue instance I set mobile = false, then by clicking the hamburger I can toggle it and therefore transition the off-canvas nav in.



      navigation.scss:



      @media only screen and (min-width: $tablet) 
      ul
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(100px, auto));
      > li
      margin: 0 auto;


      .toggle
      display: none;



      @media only screen and (max-width: $tablet - 1px)
      nav
      position: fixed;
      top: 0;
      bottom: 0;
      width: $nav;
      right: -$nav;

      nav,
      header,
      section#main,
      footer
      transition: transform .7s ease-in-out;

      .nav-open
      transform: translateX(-$nav);




      My main layout.scss:



      /*! Mobile View */

      #root
      display: grid;
      grid-template-columns: 1fr;


      /*! Desktop View */

      #root > section #main
      margin: 0 auto;
      @media only screen and (min-width: $tablet)
      display: grid;
      grid-column-gap: 20px;
      grid-template-columns: repeat(10, 1fr);
      main
      grid-column: span 7;

      aside
      grid-column: span 3;


      @media only screen and (min-width: $desktop)
      width: 90%;




      Obviously this is just scaffolding. In the end I'm not sure about 3 things:



      • Should I keep the mobile / off-canvas navigation as a vue component, or incorporate in my layout scss files? I did it because because this way all the styling, JavaScript and HTML is contained in a single file. On the other hand, the way I learned it, one should create a component if one wants to reuse a particular piece of code more than once, which I'm obviously not doing here. I'm only using it once. Is it still viable (also in terms of performance)?


      • One thing I'm unsure about is :class=" 'nav-open' : mobile " in my markup. The way I build it I have repeat it several times in my markup (once for sliding in the off-canvas nav, but also three times for sliding out (to the right) the header, main section and footer). It's repetitive, but I don't know if it can be done better.


      • Would you have setup the Grid similarly using CSS Grid, or should I change something? I was trying to scaffold it with mobile-first in mind, while being as minimal / performant as possible.







      share|improve this question













      I've recently been getting into VueJS and CSS Grid. In the past I've always used frameworks like Bootstrap to built up my layout. However, since CSS Grids and VueJS have caught my attention, I'm trying to build a responsive layout using both.



      My question now is, can (or should) one generally use vue components for the basic layout? I've built an off-canvas navigation for smaller viewpoints and turned it into a vue component:



      hamburger.vue:



      <template>
      <div class="hamburger">
      <div class="bar" :class=" 'bar-top' : this.text "></div>
      <div class="bar" :class=" 'bar-middle' : this.text "></div>
      <div class="bar" :class=" 'bar-bottom' : this.text "></div>
      </div>
      </template>

      <script>
      export default
      props: ['text']

      </script>

      <style lang="scss" scoped>
      @import "../../../sass/core/_variables";

      .hamburger
      position: absolute;
      right: 15px;
      top: 15px;
      display: block;
      cursor: pointer;
      transition: transform .7s ease-in-out;

      @media only screen and (min-width: $tablet)
      display: none;


      .bar
      width: 30px;
      height: 4px;
      margin-bottom: 5px;
      background-color: #000000;
      border-radius: 3px;
      transition: all .7s ease;

      .bar:last-child
      margin-bottom: 0px;

      .bar-top
      transform: translateY(9px) rotateZ(45deg);

      .bar-middle
      opacity: 0;

      .bar-bottom
      transform: translateY(-10px) rotateZ(-45deg);

      </style>


      And I am including it in my main layout like so:



      <div id="root">
      <header role="banner" :class=" 'nav-open' : mobile ">
      <div class="container">
      <h2>Header</h2>
      <hamburger :text="mobile" @click.native="mobile = !mobile"> </hamburger>
      </div>
      <section class="hero is-dark is-bold">
      <div class="hero-body">
      <div class="container">
      <h1 class="title">Hero title</h1>
      <h2 class="subtitle">Hero subtitle</h2>
      </div>
      </div>
      </section>
      </header>
      <nav role="navigation" :class=" 'nav-open' : mobile ">
      <div class="container">
      <ul>
      <li>Item 1</li>
      <li>Item 2</li>
      <li>Item 3</li>
      <li>Item 4</li>
      <li>Item 5</li>
      <li>Item 6</li>
      </ul>
      </div>
      </nav>
      <section id="main" :class=" 'nav-open' : mobile ">
      <main role="main">
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
      </main>
      <aside>
      <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim.</p>
      </aside>
      </section>
      <footer role="footer" :class=" 'nav-open' : mobile ">
      <div class="container">
      <h2>Footer</h2>
      </div>
      </footer>
      </div>


      So the way it works is, on my vue instance I set mobile = false, then by clicking the hamburger I can toggle it and therefore transition the off-canvas nav in.



      navigation.scss:



      @media only screen and (min-width: $tablet) 
      ul
      display: grid;
      grid-template-columns: repeat(auto-fit, minmax(100px, auto));
      > li
      margin: 0 auto;


      .toggle
      display: none;



      @media only screen and (max-width: $tablet - 1px)
      nav
      position: fixed;
      top: 0;
      bottom: 0;
      width: $nav;
      right: -$nav;

      nav,
      header,
      section#main,
      footer
      transition: transform .7s ease-in-out;

      .nav-open
      transform: translateX(-$nav);




      My main layout.scss:



      /*! Mobile View */

      #root
      display: grid;
      grid-template-columns: 1fr;


      /*! Desktop View */

      #root > section #main
      margin: 0 auto;
      @media only screen and (min-width: $tablet)
      display: grid;
      grid-column-gap: 20px;
      grid-template-columns: repeat(10, 1fr);
      main
      grid-column: span 7;

      aside
      grid-column: span 3;


      @media only screen and (min-width: $desktop)
      width: 90%;




      Obviously this is just scaffolding. In the end I'm not sure about 3 things:



      • Should I keep the mobile / off-canvas navigation as a vue component, or incorporate in my layout scss files? I did it because because this way all the styling, JavaScript and HTML is contained in a single file. On the other hand, the way I learned it, one should create a component if one wants to reuse a particular piece of code more than once, which I'm obviously not doing here. I'm only using it once. Is it still viable (also in terms of performance)?


      • One thing I'm unsure about is :class=" 'nav-open' : mobile " in my markup. The way I build it I have repeat it several times in my markup (once for sliding in the off-canvas nav, but also three times for sliding out (to the right) the header, main section and footer). It's repetitive, but I don't know if it can be done better.


      • Would you have setup the Grid similarly using CSS Grid, or should I change something? I was trying to scaffold it with mobile-first in mind, while being as minimal / performant as possible.









      share|improve this question












      share|improve this question




      share|improve this question








      edited Jan 27 at 22:43









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Jan 27 at 22:27









      Artemios Antonio Balbach

      161




      161




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          0
          down vote













          I noticed that this question has been unanswered for some time, so I'll try to at least partially review your code.



          Components re-use



          Components are simply abstractions, an encapsulation of something that can stand on its own. If it is re-usable, that would be great, but it is not a requirement to make something their own component.



          A navigation bar is something that can stand on it's own, so I would recommend putting it in a separate component, together with its styling. If most of your components are self-contained, your code will stay easy to reason about.



          Repeated class definitions



          You should move :class=" 'nav-open' : mobile " to the top-most element in your application. In your separate navigation, and footer, and header component you can then use the following SCSS:





          // Namespacing of all your css
          .navigation
          // css if your navigation is closed

          .nav-open &
          // css if your navigation is opened




          This makes sure that whatever future element you make that needs to do something when your navigation opens can do so without a problem, even if you change your layout significantly.



          Opening and closing your navigation



          You currently have your navigation and hamburger icon in the same file. This works, for now, but if your header, footer and navigation get bigger, your App.vue will become really bloated. I recommend using Vuex to keep the global state of the navigation bar, or a bus such as this one if you do not want to create a state.



          You can then do this:



          App.vue



          <template>
          <div :class="appClasses">
          <app-header />
          <app-navigation />
          <app-footer />
          </div>
          </template>

          <script>
          import mapGetters from 'vuex'

          export default
          name: 'app',
          computed:
          ...mapGetters('global', ['navigationOpen']),

          appClasses ()
          return
          'my-app': true,
          'nav-open': this.navigationOpen




          </script>

          <style lang="scss">
          .my-app
          // There should be very little css in your App.vue file

          </style>


          A header.vue with a hamburger that toggles the menu



          <template>
          <header class="app-header">
          <hamburger-menu @click="toggleMenu" />
          </header>
          </template>

          <script>
          export default
          name: 'app-header',
          methods:
          toggleMenu ()
          this.$store.commit('global/toggleNavigation')



          </script>

          <style lang="scss">
          .app-header
          // Hopefully a bit more css here

          </style>


          And a store/modules/global.js file:



          const state = 
          navigationOpen: false


          const getters =
          navigationOpen (state)
          return state.navigationOpen



          const mutations =
          toggleNavigation (state)
          state.navigationOpen = !state.navigationOpen



          export default
          state,
          getters,
          mutations



          Avoid external scss files



          The strength of Vue comes in that all javascript, styling and markup is in a single component file. If you move styling to a separate file, you are sort of defeating this strength as developers are required to switch between files again.



          As a rule of thumb, try to limit external scss files to only contain variables, mixins and external dependencies.



          Imports in components



          You import a file with variables in one of your components. From experience I know this will get old really fast. I recommend splitting your external scss files in two parts:



          • Files that only contain variables and mixins, but no actual styling

          • Files that contain styling

          You include the main styling file in your App.vue, so it only gets included once. The main variable/mixin file can be added to your webpack config, so that any scss in your component files can use those variables and mixins without an explicit import.



          Odd naming of property



          Your property this.text in your hamburger menu is named oddly. It seems to serve some purpose of making the hamburger visible, so I would recommend renaming it to visible. You can then add it as a single class to the div with class hamburger and style it from there.



          Scss and scoped



          The scoped attribute on your style tag makes Vue add a component identifying attribute to all html elements in that component. This is great when you have classes that could be used by other components or other elements on the same page, but also makes the generated html look rather ugly.



          In most cases, the same can be accomplished by using unique names for your components and adding a class to the root element of that component. Then you can style your components by "namespacing" your css:



          <template>
          <div class="my-component">
          </div>
          </template>

          <script>
          export default
          name: 'my-component'

          </script>

          <style lang="scss">
          .my-component
          .btn
          // Styling will only be applied to buttons within this component


          </style>





          share|improve this answer





















            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186159%2fuse-vue-components-as-one-offs-in-layout-scaffolding%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            0
            down vote













            I noticed that this question has been unanswered for some time, so I'll try to at least partially review your code.



            Components re-use



            Components are simply abstractions, an encapsulation of something that can stand on its own. If it is re-usable, that would be great, but it is not a requirement to make something their own component.



            A navigation bar is something that can stand on it's own, so I would recommend putting it in a separate component, together with its styling. If most of your components are self-contained, your code will stay easy to reason about.



            Repeated class definitions



            You should move :class=" 'nav-open' : mobile " to the top-most element in your application. In your separate navigation, and footer, and header component you can then use the following SCSS:





            // Namespacing of all your css
            .navigation
            // css if your navigation is closed

            .nav-open &
            // css if your navigation is opened




            This makes sure that whatever future element you make that needs to do something when your navigation opens can do so without a problem, even if you change your layout significantly.



            Opening and closing your navigation



            You currently have your navigation and hamburger icon in the same file. This works, for now, but if your header, footer and navigation get bigger, your App.vue will become really bloated. I recommend using Vuex to keep the global state of the navigation bar, or a bus such as this one if you do not want to create a state.



            You can then do this:



            App.vue



            <template>
            <div :class="appClasses">
            <app-header />
            <app-navigation />
            <app-footer />
            </div>
            </template>

            <script>
            import mapGetters from 'vuex'

            export default
            name: 'app',
            computed:
            ...mapGetters('global', ['navigationOpen']),

            appClasses ()
            return
            'my-app': true,
            'nav-open': this.navigationOpen




            </script>

            <style lang="scss">
            .my-app
            // There should be very little css in your App.vue file

            </style>


            A header.vue with a hamburger that toggles the menu



            <template>
            <header class="app-header">
            <hamburger-menu @click="toggleMenu" />
            </header>
            </template>

            <script>
            export default
            name: 'app-header',
            methods:
            toggleMenu ()
            this.$store.commit('global/toggleNavigation')



            </script>

            <style lang="scss">
            .app-header
            // Hopefully a bit more css here

            </style>


            And a store/modules/global.js file:



            const state = 
            navigationOpen: false


            const getters =
            navigationOpen (state)
            return state.navigationOpen



            const mutations =
            toggleNavigation (state)
            state.navigationOpen = !state.navigationOpen



            export default
            state,
            getters,
            mutations



            Avoid external scss files



            The strength of Vue comes in that all javascript, styling and markup is in a single component file. If you move styling to a separate file, you are sort of defeating this strength as developers are required to switch between files again.



            As a rule of thumb, try to limit external scss files to only contain variables, mixins and external dependencies.



            Imports in components



            You import a file with variables in one of your components. From experience I know this will get old really fast. I recommend splitting your external scss files in two parts:



            • Files that only contain variables and mixins, but no actual styling

            • Files that contain styling

            You include the main styling file in your App.vue, so it only gets included once. The main variable/mixin file can be added to your webpack config, so that any scss in your component files can use those variables and mixins without an explicit import.



            Odd naming of property



            Your property this.text in your hamburger menu is named oddly. It seems to serve some purpose of making the hamburger visible, so I would recommend renaming it to visible. You can then add it as a single class to the div with class hamburger and style it from there.



            Scss and scoped



            The scoped attribute on your style tag makes Vue add a component identifying attribute to all html elements in that component. This is great when you have classes that could be used by other components or other elements on the same page, but also makes the generated html look rather ugly.



            In most cases, the same can be accomplished by using unique names for your components and adding a class to the root element of that component. Then you can style your components by "namespacing" your css:



            <template>
            <div class="my-component">
            </div>
            </template>

            <script>
            export default
            name: 'my-component'

            </script>

            <style lang="scss">
            .my-component
            .btn
            // Styling will only be applied to buttons within this component


            </style>





            share|improve this answer

























              up vote
              0
              down vote













              I noticed that this question has been unanswered for some time, so I'll try to at least partially review your code.



              Components re-use



              Components are simply abstractions, an encapsulation of something that can stand on its own. If it is re-usable, that would be great, but it is not a requirement to make something their own component.



              A navigation bar is something that can stand on it's own, so I would recommend putting it in a separate component, together with its styling. If most of your components are self-contained, your code will stay easy to reason about.



              Repeated class definitions



              You should move :class=" 'nav-open' : mobile " to the top-most element in your application. In your separate navigation, and footer, and header component you can then use the following SCSS:





              // Namespacing of all your css
              .navigation
              // css if your navigation is closed

              .nav-open &
              // css if your navigation is opened




              This makes sure that whatever future element you make that needs to do something when your navigation opens can do so without a problem, even if you change your layout significantly.



              Opening and closing your navigation



              You currently have your navigation and hamburger icon in the same file. This works, for now, but if your header, footer and navigation get bigger, your App.vue will become really bloated. I recommend using Vuex to keep the global state of the navigation bar, or a bus such as this one if you do not want to create a state.



              You can then do this:



              App.vue



              <template>
              <div :class="appClasses">
              <app-header />
              <app-navigation />
              <app-footer />
              </div>
              </template>

              <script>
              import mapGetters from 'vuex'

              export default
              name: 'app',
              computed:
              ...mapGetters('global', ['navigationOpen']),

              appClasses ()
              return
              'my-app': true,
              'nav-open': this.navigationOpen




              </script>

              <style lang="scss">
              .my-app
              // There should be very little css in your App.vue file

              </style>


              A header.vue with a hamburger that toggles the menu



              <template>
              <header class="app-header">
              <hamburger-menu @click="toggleMenu" />
              </header>
              </template>

              <script>
              export default
              name: 'app-header',
              methods:
              toggleMenu ()
              this.$store.commit('global/toggleNavigation')



              </script>

              <style lang="scss">
              .app-header
              // Hopefully a bit more css here

              </style>


              And a store/modules/global.js file:



              const state = 
              navigationOpen: false


              const getters =
              navigationOpen (state)
              return state.navigationOpen



              const mutations =
              toggleNavigation (state)
              state.navigationOpen = !state.navigationOpen



              export default
              state,
              getters,
              mutations



              Avoid external scss files



              The strength of Vue comes in that all javascript, styling and markup is in a single component file. If you move styling to a separate file, you are sort of defeating this strength as developers are required to switch between files again.



              As a rule of thumb, try to limit external scss files to only contain variables, mixins and external dependencies.



              Imports in components



              You import a file with variables in one of your components. From experience I know this will get old really fast. I recommend splitting your external scss files in two parts:



              • Files that only contain variables and mixins, but no actual styling

              • Files that contain styling

              You include the main styling file in your App.vue, so it only gets included once. The main variable/mixin file can be added to your webpack config, so that any scss in your component files can use those variables and mixins without an explicit import.



              Odd naming of property



              Your property this.text in your hamburger menu is named oddly. It seems to serve some purpose of making the hamburger visible, so I would recommend renaming it to visible. You can then add it as a single class to the div with class hamburger and style it from there.



              Scss and scoped



              The scoped attribute on your style tag makes Vue add a component identifying attribute to all html elements in that component. This is great when you have classes that could be used by other components or other elements on the same page, but also makes the generated html look rather ugly.



              In most cases, the same can be accomplished by using unique names for your components and adding a class to the root element of that component. Then you can style your components by "namespacing" your css:



              <template>
              <div class="my-component">
              </div>
              </template>

              <script>
              export default
              name: 'my-component'

              </script>

              <style lang="scss">
              .my-component
              .btn
              // Styling will only be applied to buttons within this component


              </style>





              share|improve this answer























                up vote
                0
                down vote










                up vote
                0
                down vote









                I noticed that this question has been unanswered for some time, so I'll try to at least partially review your code.



                Components re-use



                Components are simply abstractions, an encapsulation of something that can stand on its own. If it is re-usable, that would be great, but it is not a requirement to make something their own component.



                A navigation bar is something that can stand on it's own, so I would recommend putting it in a separate component, together with its styling. If most of your components are self-contained, your code will stay easy to reason about.



                Repeated class definitions



                You should move :class=" 'nav-open' : mobile " to the top-most element in your application. In your separate navigation, and footer, and header component you can then use the following SCSS:





                // Namespacing of all your css
                .navigation
                // css if your navigation is closed

                .nav-open &
                // css if your navigation is opened




                This makes sure that whatever future element you make that needs to do something when your navigation opens can do so without a problem, even if you change your layout significantly.



                Opening and closing your navigation



                You currently have your navigation and hamburger icon in the same file. This works, for now, but if your header, footer and navigation get bigger, your App.vue will become really bloated. I recommend using Vuex to keep the global state of the navigation bar, or a bus such as this one if you do not want to create a state.



                You can then do this:



                App.vue



                <template>
                <div :class="appClasses">
                <app-header />
                <app-navigation />
                <app-footer />
                </div>
                </template>

                <script>
                import mapGetters from 'vuex'

                export default
                name: 'app',
                computed:
                ...mapGetters('global', ['navigationOpen']),

                appClasses ()
                return
                'my-app': true,
                'nav-open': this.navigationOpen




                </script>

                <style lang="scss">
                .my-app
                // There should be very little css in your App.vue file

                </style>


                A header.vue with a hamburger that toggles the menu



                <template>
                <header class="app-header">
                <hamburger-menu @click="toggleMenu" />
                </header>
                </template>

                <script>
                export default
                name: 'app-header',
                methods:
                toggleMenu ()
                this.$store.commit('global/toggleNavigation')



                </script>

                <style lang="scss">
                .app-header
                // Hopefully a bit more css here

                </style>


                And a store/modules/global.js file:



                const state = 
                navigationOpen: false


                const getters =
                navigationOpen (state)
                return state.navigationOpen



                const mutations =
                toggleNavigation (state)
                state.navigationOpen = !state.navigationOpen



                export default
                state,
                getters,
                mutations



                Avoid external scss files



                The strength of Vue comes in that all javascript, styling and markup is in a single component file. If you move styling to a separate file, you are sort of defeating this strength as developers are required to switch between files again.



                As a rule of thumb, try to limit external scss files to only contain variables, mixins and external dependencies.



                Imports in components



                You import a file with variables in one of your components. From experience I know this will get old really fast. I recommend splitting your external scss files in two parts:



                • Files that only contain variables and mixins, but no actual styling

                • Files that contain styling

                You include the main styling file in your App.vue, so it only gets included once. The main variable/mixin file can be added to your webpack config, so that any scss in your component files can use those variables and mixins without an explicit import.



                Odd naming of property



                Your property this.text in your hamburger menu is named oddly. It seems to serve some purpose of making the hamburger visible, so I would recommend renaming it to visible. You can then add it as a single class to the div with class hamburger and style it from there.



                Scss and scoped



                The scoped attribute on your style tag makes Vue add a component identifying attribute to all html elements in that component. This is great when you have classes that could be used by other components or other elements on the same page, but also makes the generated html look rather ugly.



                In most cases, the same can be accomplished by using unique names for your components and adding a class to the root element of that component. Then you can style your components by "namespacing" your css:



                <template>
                <div class="my-component">
                </div>
                </template>

                <script>
                export default
                name: 'my-component'

                </script>

                <style lang="scss">
                .my-component
                .btn
                // Styling will only be applied to buttons within this component


                </style>





                share|improve this answer













                I noticed that this question has been unanswered for some time, so I'll try to at least partially review your code.



                Components re-use



                Components are simply abstractions, an encapsulation of something that can stand on its own. If it is re-usable, that would be great, but it is not a requirement to make something their own component.



                A navigation bar is something that can stand on it's own, so I would recommend putting it in a separate component, together with its styling. If most of your components are self-contained, your code will stay easy to reason about.



                Repeated class definitions



                You should move :class=" 'nav-open' : mobile " to the top-most element in your application. In your separate navigation, and footer, and header component you can then use the following SCSS:





                // Namespacing of all your css
                .navigation
                // css if your navigation is closed

                .nav-open &
                // css if your navigation is opened




                This makes sure that whatever future element you make that needs to do something when your navigation opens can do so without a problem, even if you change your layout significantly.



                Opening and closing your navigation



                You currently have your navigation and hamburger icon in the same file. This works, for now, but if your header, footer and navigation get bigger, your App.vue will become really bloated. I recommend using Vuex to keep the global state of the navigation bar, or a bus such as this one if you do not want to create a state.



                You can then do this:



                App.vue



                <template>
                <div :class="appClasses">
                <app-header />
                <app-navigation />
                <app-footer />
                </div>
                </template>

                <script>
                import mapGetters from 'vuex'

                export default
                name: 'app',
                computed:
                ...mapGetters('global', ['navigationOpen']),

                appClasses ()
                return
                'my-app': true,
                'nav-open': this.navigationOpen




                </script>

                <style lang="scss">
                .my-app
                // There should be very little css in your App.vue file

                </style>


                A header.vue with a hamburger that toggles the menu



                <template>
                <header class="app-header">
                <hamburger-menu @click="toggleMenu" />
                </header>
                </template>

                <script>
                export default
                name: 'app-header',
                methods:
                toggleMenu ()
                this.$store.commit('global/toggleNavigation')



                </script>

                <style lang="scss">
                .app-header
                // Hopefully a bit more css here

                </style>


                And a store/modules/global.js file:



                const state = 
                navigationOpen: false


                const getters =
                navigationOpen (state)
                return state.navigationOpen



                const mutations =
                toggleNavigation (state)
                state.navigationOpen = !state.navigationOpen



                export default
                state,
                getters,
                mutations



                Avoid external scss files



                The strength of Vue comes in that all javascript, styling and markup is in a single component file. If you move styling to a separate file, you are sort of defeating this strength as developers are required to switch between files again.



                As a rule of thumb, try to limit external scss files to only contain variables, mixins and external dependencies.



                Imports in components



                You import a file with variables in one of your components. From experience I know this will get old really fast. I recommend splitting your external scss files in two parts:



                • Files that only contain variables and mixins, but no actual styling

                • Files that contain styling

                You include the main styling file in your App.vue, so it only gets included once. The main variable/mixin file can be added to your webpack config, so that any scss in your component files can use those variables and mixins without an explicit import.



                Odd naming of property



                Your property this.text in your hamburger menu is named oddly. It seems to serve some purpose of making the hamburger visible, so I would recommend renaming it to visible. You can then add it as a single class to the div with class hamburger and style it from there.



                Scss and scoped



                The scoped attribute on your style tag makes Vue add a component identifying attribute to all html elements in that component. This is great when you have classes that could be used by other components or other elements on the same page, but also makes the generated html look rather ugly.



                In most cases, the same can be accomplished by using unique names for your components and adding a class to the root element of that component. Then you can style your components by "namespacing" your css:



                <template>
                <div class="my-component">
                </div>
                </template>

                <script>
                export default
                name: 'my-component'

                </script>

                <style lang="scss">
                .my-component
                .btn
                // Styling will only be applied to buttons within this component


                </style>






                share|improve this answer













                share|improve this answer



                share|improve this answer











                answered May 12 at 8:42









                Sumurai8

                2,260315




                2,260315






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f186159%2fuse-vue-components-as-one-offs-in-layout-scaffolding%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Chat program with C++ and SFML

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    Will my employers contract hold up in court?