Using Atomic Design with Nuxt.js and have a great hacking time. 
Tags: vue, nuxt, javascript, frontend
Published: 2019-04-16 14:34:31

---
title: Using Atomic Design with Nuxt.js and have a great hacking time. 
published: true
description: 
tags: #Vue.js #Nuxt.js #Javascript #Frontend
---

This is my first time write a english post.
I'm a web application developer working in Japan.And yes, I'm a Chinese.XD

What I used in this project
---
Nuxt.js v2.0
Express v4.0
bootstrap-vue v4.0

What is Atomic Design
---
In case you don't know what is Atomic Design.
Here are some good documents about it.

http://atomicdesign.bradfrost.com/
https://www.indetail.co.jp/blog/10234/

TL;Dr: It's a design system to show you how to create your UI component exactly you need to use.


How To Separate Your Folder
---
components
|
|---- atoms
|------ |---Album.vue
|------ |---BackBtn.vue
|---- molecules 
|------ |---AlbumList.vue
|---- organisms
|------ |---AlbumBook.vue
|---- page
|------ |---AlbumBooks.vue

Atoms Samples
---
The smallest UI component in your project.
Like this. Just a nuxt-lint, div and img.
``` Vue
<template>
  <div>
    <nuxt-link to="/album">
      <img class="album-image" :src="album.coverUrl" />
    </nuxt-link>
    <div>
      {{ album.title }}
    </div>
  </div>
</template>

<script>
export default {
  props: {
    album: {
      type: Object,
      required: true,
      default: null
    }
  }
}
</script>

<style scoped>  <-- Use scoped to make the css only in this component
.album-image {
  height: 175px;
  width: 175px;
  object-fit: cover;
  border-radius: 10px;
  margin: 1px;
}
</style>
```

molecules
---
contain some atoms
In my case, I make it to be a array of the atoms

```Vue
<template>
  <b-row>
    <b-col v-for="album in albums" :key="album.id">
      <Album :album="album"></Album>  <!-- use props in atom to receive the data -->
    </b-col>
  </b-row>
</template>

<script>
import Album from '~/components/atoms/Album.vue'  //  import the atom file

export default {
  components: {
    Album // This is the atom componet
  },

  props: {
    data: {
      type: Object,
      required: true,
      default: () => null
    }
  }
}
</script>
```

organisms
---
combine different molecules

```Vue
<template>
  <section>
    <nav class="navbar navbar-light bg-light">
      <BackBtn path="/activity"></BackBtn>  <--- You can use atom aslo
    </nav>
    <div class="container-fluid">
      <AlbumList :data="albums"></AlbumList>  
      <CommentList :comments="comments"></CommentList>
    </div>
  </section>
</template>

<script>
import BackBtn from '~/components/atoms/BackBtn.vue'
import CommentList from '~/components/molecules/CommentList.vue'
import AlbumList from '~/components/molecules/AlbumList.vue'

export default { 
  components: {
    BackBtn, 
    CommentList, // different molecules
    AlbumList    // some molecules
  }
  data() {
    comments: [
       ... // 
    ]
  },
  computed: {
    albums() {
      return this.$store.state.albums // Using Vuex with Atomic Design is aslo a great idea, you can get your data in different ways.In your atom or your molecules.
    }
  },
}
</script>

```


Page
---
Finally, The page.
Make sure your page using less code you need.
If your page is larger you should think about to separate into small things like atom.

```Vue
<template>
  <section>
    <AlbumBook></AlbumBook>
  </section>
</template>

<script>
import AlbumBook from '~/components/organisms/AlbumBook.vue'

export default {
  components: {
    AlbumBook
  }
}
</script>
```

At Last
---
Separate your files, decide which component should be smaller. Maybe is the most challenge thing in your project.
But once you get to the point. you'll get the benefit from it. 
Especially in your early development stage.

1.Every time you want to change your component. You don't need to change them all.Just in one file.Any other your page import that file can be changed.

2.Easy for management.Less code you need, Less bugs.

P.S:
This post is what I wrote in my Qiita.(A Japanese Tech blog)
https://qiita.com/jakushin/items/e8b19f6a2c7bcd037573