0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

軽くNuxtJSを触る

Last updated at Posted at 2021-01-31

やること

  • NuxtJSインストール
  • ページの追加
  • storeの確認
  • propsとslotの確認
  • $emitの確認
  • middlewareの確認
  • layoutの確認

コード

yoshida-san/nuxt-sample

プロジェクト作成

~$ npx nuxt-create-app nuxt-sample

設定内容は以下の通り。

? Programming language: JavaScript
? Package manager: Npm
? UI framework: None
? Nuxt.js modules: Axios - Promise based HTTP client
? Linting tools: ESLint, Prettier
? Testing framework: Jest
? Rendering mode: Single Page App
? Deployment target: Server (Node.js hosting)
? Development tools: jsconfig.json, Dependabot
? Continuous integration: None
? Version control system: Git

動かしてみる(当然のように動く)。

~$ cd nuxt-sample
~$ npm run dev

ホットリロードは便利。

構成確認

初期状態は以下の通り。
ファイルには先頭に📄を付加してます。
各ディレクトリとファイルの説明はディレクトリ構成 - NuxtJS.nuxt - NuxtJSに書いてある。

rootDir
 ├ .github
 │  └ 📄dependabot.yml
 ├ assets
 ├ components
 ├ layouts
 ├ middleware
 ├ node_modules
 ├ pages
 ├ plugins
 ├ static
 ├ store
 ├ test
 ├ 📄.babelrc
 ├ 📄.editorconfig
 ├ 📄.eslintrc.js
 ├ 📄.gitignore
 ├ 📄.prettierrc
 ├ 📄jest.config.js
 ├ 📄jsconfig.json
 ├ 📄nuxt.config.js
 ├ 📄package-lock.json
 ├ 📄package.json
 └ 📄README.md

middlewareに関してはexpressのmiddleware的な感じ?
pluginsは普通にロジックを切り出して置いておくディレクトリですかね。

ページを追加する

Nuxtはvue-routerをいい感じにラップしてくれているのでページの追加は/pagesにany.vueを追加するだけです。hoge.vueを追加すれば/hogeでアクセスできます。/hoge/index.vueのようにディレクトリを切ってindex.vueを用意する形でもOK。
.vueからstyleやscriptを切り離すならディレクトリを作成した方が良さそうな印象(scriptも共通処理はpluginsに入ると思いますが)。

Vuterのインストール

VSCodeでコードを書くのでVuterをインストール。
最新バージョンをインストールしたらformatOnSave設定と何か干渉しているのかいつまでも保存が終わらない...Getting code actions from ''Vetur', 'Eslint'' takes too long!を参照してversionを0.25.0に下げることで解決。

先人の知恵はありがたい。

store

store確認用のインクリメントボタン、デクリメントボタン、テキストのatomを用意してそれっぽいcomponentを作ってみる。storeも作る。

index.vue

<template>
  <div class="container">
    <section>
      <Counter />
    </section>
  </div>
</template>

<script>
export default {
  // logic
}
</script>

<style scoped>
.container {
  margin: 0 auto;
  min-height: 100vh;
  display: flex;
  justify-content: center;
  align-items: center;
  text-align: center;
}
</style>

/components/atoms/CounterLabel.vue

<template>
  <label>{{ $store.state.counter }}</label>
</template>

/components/atoms/IncrementButton.vue

<template>
  <button @click="increment">+</button>
</template>

<script>
export default {
  methods: {
    increment() {
      this.$store.commit('increment')
    },
  },
}
</script>

/components/atoms/DecrementButton.vue

<template>
  <button @click="decrement">-</button>
</template>

<script>
export default {
  methods: {
    decrement() {
      this.$store.commit('decrement')
    },
  },
}
</script>

/components/Counter.vue

<template>
  <div>
    <div>
      <CounterLabel />
    </div>
    <div>
      <IncrementButton />
      <DecrementButton />
    </div>
  </div>
</template>

/store/index.js

export const state = () => ({
  counter: 0,
})

export const mutations = {
  increment(state) {
    state.counter++
  },
  decrement(state) {
    state.counter--
  },
}

できた(気がする

props / slot

propsとslotの使い分けとかは割愛。

/components/atoms/IncrementButton.vue

<template>
  <button @click="increment">{{ text }}</button>
</template>

<script>
export default {
  props: {
    text: {
      type: String,
      default: 'Increment',
    },
  },
  methods: {
    increment() {
      this.$store.commit('increment')
    },
  },
}
</script>

/components/atoms/DecrementButton.vue

<template>
  <button @click="decrement"><slot /></button>
</template>

<script>
export default {
  methods: {
    decrement() {
      this.$store.commit('decrement')
    },
  },
}
</script>

/components/Counter.vue

<template>
  <div>
    <div>
      <CounterLabel />
    </div>
    <div>
      <IncrementButton text="+" />
      <DecrementButton><slot>Decrement</slot></DecrementButton>
    </div>
  </div>
</template>

slotを複数使う時は名前付きslotを使いましょうねと。

$emit

Child Componentの値やイベントを親に渡す時に使う。値はstoreで管理すれば良いし、イベントはmethodを渡せば良いのでは???って思ってるけど多分何か違うんだろうなぁ...。
一気に見通しが悪くなった気がするけど慣れてないだけかな...。

/components/Counter.vue

<template>
  <div>
    <div>
      <CounterLabel />
    </div>
    <div>
      <IncrementButton text="+" @welcome="say" />
      <DecrementButton><slot>Decrement</slot></DecrementButton>
      <SayButton @sayCount="say" />
    </div>
  </div>
</template>

<script>
export default {
  methods: {
    say(val) {
      alert(val)
    },
  },
}
</script>

/components/atoms/SayButton.vue

<template>
  <button @click="sayCount">Say</button>
</template>

<script>
export default {
  methods: {
    sayCount() {
      this.$emit('sayCount', this.$store.state.counter)
    },
  },
}
</script>

middleware

レンダリング前に処理をしたい場合はmiddlewareを使う。middlewareディレクトリ内に処理を定義して、pagesディレクトリ内の.vueでどの処理を適用させるか定義する。

/middleware/sampleMiddleware.js

export default function (context) {
  console.log('middleware!')
  console.dir(context)
}

/pages/index.vue

<template>
  <div class="container">
    <section>
      <Counter />
    </section>
  </div>
</template>

<script>
export default {
  middleware: 'sampleMiddleware',
}
</script>

layout

Webページのレイアウトを定義できる。pagesディレクトリ内の.vueでどのレイアウトを使用するか定義できる。middlewareと組み合わせてあれこれできそう。

/layout/default.vue

<template>
  <div>
    <h1>default.vue</h1>
    <Nuxt />
  </div>
</template>

<style>
:
</style>

/layout/sampleLayout.vue

<template>
  <div>
    <h1>sampleLayout.vue</h1>
    <Nuxt />
  </div>
</template>

<style>
:
</style>

/pages/index.vue

<template>
  <div class="container">
    <section>
      <Counter />
    </section>
  </div>
</template>

<script>
export default {
  layout: 'sampleLayout',  // switch layout
  middleware: 'sampleMiddleware',
}
</script>

<style scoped>
:
</style>

おわり

一息入れたらnamespaceやmodulesも触っておこうと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?