Help us understand the problem. What is going on with this article?

web制作でよく使用するVuex自作モジュール3選

More than 1 year has passed since last update.

ここ数ヶ月、webサイトをつくときはVueまたはVuePressを使用しています。
いくつか作ってみてほぼ必ず必要になってるVuexの自作モジュールがあるので3つほどご紹介

とりあえずこの3つをVuexつかって管理して必要なコンポーネントでmapState
などすると実装がシンプルになるような気がします。

とりあえずindex.js

store/index.jsとかつくってとりあえず置いておく。基本は用途ごとにネームスペースを切る想定。

index.js
import Vue from 'vue'
import Vuex from 'Vuex'

const state = {
}

const modules = {

}

const mutations = {

}

const actions = {

}

const store = new Vuex.Store({
  state,
  modules,
  mutations,
  actions,
})

export default store;

レスポンシブ、画面サイズに関するモジュール

レスポンシブでウェブサイトを作っているとウインドウサイズの情報が欲しくなったり、
モバイルでは必要だけどPCでは必要ないみたいなことが頻繁に起こります。
windowに関する情報はstoreで管理してます。

store/module-window.js

module-window.js
const mobileThreshold = 769;
const minWidth = 1280;

const decideIsPc = (w)=>{
  if(w < mobileThreshold){
    return false;
  }
  return true;
}

const getWindowSize = ()=>{
  let w = window.innerWidth
  let h = window.innerHeight
  if(w >= mobileThreshold) w = Math.max(minWidth, w);
  return {
    w: w,
    h: h
  }
}


const defaultState = typeof window !== 'undefined' ? {
  size: getWindowSize(),
  isPc: decideIsPc(window.innerWidth)
} : {
  size: {w: 999999, h: 999999},
  isPc: true,
}

const state = defaultState;

const mutations = {
  update(state){
    const size = getWindowSize();
    state.size = size
    state.isPc = decideIsPc(size.w);
  },
}


export default {
  namespaced: true,
  state,
  mutations
}

VuePressでビルドする用(おそらくNuxtでも同じ)にtypeof windowとかで条件分岐しているため
やや冗長になってますが、やっていることはmutationupdateでウインドウサイズ取得して
サイズを更新、ついでにモバイルかどうかも変別して更新しているだけです。

store/index.jsにモジュールをついかするのと、(どこに書いても問題ないが)window resizeをフックする
部分もここに書いてしまっています。

index.js
~
import ModuleWindow from './module-window'

~

const modules = {
  window: ModuleWindow,
}

~

if(typeof window !== 'undefined'){

  window.addEventListener('resize', ()=>{
    store.commit('window/update')
  })

}

storeのisPcはよく使うのでなんならmixinにしてもいいかもしれません。

import {mapState} from 'Vuex'
Vue.mixin({
  computed:{
    ...mapState('window', {$isPc: 'isPc'}),
  }
})

スクロール位置に関するモジュール

ウインドウサイズと同じくスクロール位置に関してもたまに必要になるので
ほとんど同じだけれど作っておくと便利かもしれません。

store/module-scroll.js

module-scroll.js
const state = {
  top: 0,
  left: 0
}

const mutations = {
  update(state){
    const elem = document.documentElement || document.body
    const top = elem.scrollTop
    const left = elem.scrollLeft
    state.top = top
    state.left = left
  }
}

const actions = {

}

const getters = {

}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
  getters
}

updateでスクロール位置調べてstate更新してるだけ。
updateを呼び出すのをウインドウと同じくstore/index.jsに書いておきます。

index.js
~
import ModuleScroll from './module-scroll'

~

const modules = {
  scroll: ModuleScroll,
}

~

if(typeof window !== 'undefined'){

  window.addEventListener('scroll', ()=>{
    store.commit('scroll/update')
  })

}

モーダルウインドウに関するモジュール

モーダルウインドウってつくるのめんどくさいですよね。
状態をVuexで管理すれば幾分ましな気持ちで実装できるんじゃないかと

module-modal.js
const state = {
  isShow: false,
}

const mutations = {
  show(state) {
    document.body.style.overflow = 'hidden'
    state.isShow = true

  },
  hide(state) {
    document.body.style.overflow = 'auto'
    state.isShow = false
  },
}

const actions = {


}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}

任意のコンポーネントでshow/hideを呼び出して、モーダルウインドウにしたいコンポーネントを
isShowとv-ifで実装するということをしています。
bodyのoverflowのスタイルを変更しているのは背景をfixさせておくためのやつです。
これだけだとios safariではカバーしきれてないのでとりあえずというところですが
この件に関しては別の話題。

modulesに追加するところは省略

おわりに

いかがだったでしょうか。特別なことをしているわけじゃないですが
なにか参考になる所があればと思います。
むしろみなさんどうしているんだろう。

sa-k0
たまになにかかきます
https://biwanoie.tokyo
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away