ここ数ヶ月、webサイトをつくときはVueまたはVuePressを使用しています。
いくつか作ってみてほぼ必ず必要になってるVuexの自作モジュールがあるので3つほどご紹介
とりあえずこの3つをVuexつかって管理して必要なコンポーネントでmapState
などすると実装がシンプルになるような気がします。
とりあえずindex.js
store/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
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
とかで条件分岐しているため
やや冗長になってますが、やっていることはmutation
のupdate
でウインドウサイズ取得して
サイズを更新、ついでにモバイルかどうかも変別して更新しているだけです。
store/index.jsにモジュールをついかするのと、(どこに書いても問題ないが)window resizeをフックする
部分もここに書いてしまっています。
~
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
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に書いておきます。
~
import ModuleScroll from './module-scroll'
~
const modules = {
scroll: ModuleScroll,
}
~
if(typeof window !== 'undefined'){
window.addEventListener('scroll', ()=>{
store.commit('scroll/update')
})
}
モーダルウインドウに関するモジュール
モーダルウインドウってつくるのめんどくさいですよね。
状態をVuexで管理すれば幾分ましな気持ちで実装できるんじゃないかと
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に追加するところは省略
おわりに
いかがだったでしょうか。特別なことをしているわけじゃないですが
なにか参考になる所があればと思います。
むしろみなさんどうしているんだろう。