Vue開発してて、これは便利だなって裏技がたくさんあるんですが、すぐ忘れてしまい毎回ググらないで済むよう、自分用のメモのつもりでまとめておきます。他にもこんなんあるで!ってのあればぜひ教えてくださいね。
(ps. Vue3 x CompositionAPI x TypeScript に移行したので、内容を書き換え中。)
環境構築、基本設定
Pug の Code Folding を有効にする (VSCode)
デフォルトの設定では、.vueファイル上でPugのインデントBlockをFoldできず不便。
setting.jsonに以下を追加するとFoldできるようになります。
{
"[vue]": {
"editor.foldingStrategy": "indentation"
}
}
ローカル開発中、ホットリロード時にコンソールをクリア
コンソールがエラーだらけになってると、ちゃんとコンパイル通ったかよくわからなくなりますよね。そんな時はこちら。変更を保存してホットリロードされる度にコンソールが綺麗になります。
if (module.hot) {
module.hot.accept()
module.hot.addStatusHandler(status => {
if (status === 'prepare') console.clear()
})
}
ローカル開発中、ターミナルの表示をシンプルにする
yarn serve
でターミナルに表示される情報をシンプルにすると、エラーを把握しやすくなるかも。
module.exports = {
devServer: {
progress: false
}
}
グローバルなfiltersは外部ファイルにまとめておく
Vue3からはFilterが非推奨になったようです。でも、頻繁に使うものについては、まとめて定義ファイルを作っておくと便利ですよね。
export default {
toPercentage (n: number): string { return (Math.round(n * 10000) / 100).toFixed(2) },
toLocaleString (val: number, decimal = 0): string {
const pow = Math.pow(10, decimal)
const rounded = Math.round(val * pow) / pow
return rounded.toFixed(decimal).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, '$1,')
}
}
グローバルで使えるようにする:
import filters from '@/filters'
const app = createApp(App)
// register global filters
app.config.globalProperties.$filters = filters
app.mount('#app')
使い方:
<template lang="pug">
section
p Balance ${{ $filters.toLocaleString(balance, 2) }}
//- 出力結果: Balance $1,234,567.89
</template>
setup()
の中で使いたい場合はやや面倒。
// getCurrentInstance をインポート
import { defineComponent, getCurrentInstance } from "vue"
export default defineComponent({
name: "App",
props: ["balance"],
setup() {
const app = getCurrentInstance(); // instanceを取得
const $filters = app.appContext.config.globalProperties.$filters; // filtersを取得
const balanceStr: string = $filters.toLocaleString(balance, 2); // filterを使う
return { balanceStr }
}
})
SCSSの変数やmixinをvueファイル内でグローバルに使えるようにする
module.exports = {
productionSourceMap: false,
css: {
loaderOptions: {
scss: {
additionalData: `
@import "~@/assets/scss/base/_variables.scss";
@import "~@/assets/scss/base/_media_queries.scss";
`
}
}
}
}
2022/5/4更新:"prependData"はsass-loader 8+から使えなくなりました。代わりに"additionalData"を使いましょう。)
コンパイルされるファイル名からハッシュを取り除く
module.exports = {
filenameHashing: false,
}
CodeSplitting やめてほしい時
module.exports = {
configureWebpack: {
optimization: {
splitChunks: false
}
}
}
Composition API Syntax
Lifecycle hooks
beforeCreate -> use setup() { ... }
created -> use setup() { ... }
beforeMount -> onBeforeMount(() => { ... })
mounted -> onMounted(() => { ... })
beforeUpdate -> onBeforeUpdate(() => { ... })
updated -> onUpdated(() => { ... })
beforeDestroy -> onBeforeUnmount(() => { ... })
destroyed -> onUnmounted(() => { ... })
errorCaptured -> onErrorCaptured(() => { ... })
Props
の Type Annotation
PropType
をインポートして使いましょう。やや面倒ですね。
import { defineComponent, PropType } from "vue";
interface Hoge {
name: string;
type: 'foo' | 'faa' | 'hoge';
age: number;
}
export default defineComponent({
name: "SectionInvestments",
props: {
hogeData: {
type: Object as PropType<Hoge>,
required: true
}
}
});
Scoped CSS のセレクタ
<style lang="scss" scoped>
// deep selectors
.a ::v-deep(.b) { ... }
// slot
::v-slotted(.b) { ... }
// global
::v-global(.b) { ... }
</style>
以下のシンタックスも議論されていましたが、今のところうまく動かない模様。
vue3.0.0で試しましたが、global扱いになってしまいます。
<style lang="scss" deep>
// deep styles
</style>
<style lang="scss" slotted>
// slotted styles
</style>
$nextTick は async/await を使ってこう書く
// nextTick をインポート
import { defineComponent, ref, onMounted, nextTick } from "vue"
export default defineComponent({
name: "App",
setup() {
onMounted(async () => {
await nextTick() // サブコンポーネントのマウントを待つ
console.log('すべてのサブコンポーネントのマウント完了!')
})
}
})
$refs へのアクセスはこうする
<template lang="pug">
#hoge(ref="hoge")
h1 Hello World!
</template>
import { defineComponent, ref } from "vue"
export default defineComponent({
name: "Hoge",
setup() {
const hoge = ref(null);
console.log(hoge.value); // ← これで#hogeにアクセスできる。
return { hoge };
}
})
Plugin 関連
重たいコンポーネントはLazyLoadしよう。
// 普通にコンポーネントを読み込む場合
import Hoge from '@/Hoge.vue'
// LazyLoadで呼ばれた時に読み込む場合
const Foo = () => import('@/Foo.vue')
その他にも、ロジックをjsファイルに切り出した場合も、WebpackでLazyLoadすると初期ロードを軽くできます。
import(/* webpackChunkName: "Hoge" */ '@/Hoge.js').then(module => {
const Hoge = module.default
Hoge.doSomething()
})
FontAwesomeを使う
参考: Font awesome を Vue.js で使ってみよう
$ yarn add @fortawesome/fontawesome-svg-core
$ yarn add @fortawesome/free-solid-svg-icons
$ yarn add @fortawesome/vue-fontawesome
import Vue from 'vue'
import { library } from '@fortawesome/fontawesome-svg-core'
import { fas } from '@fortawesome/free-solid-svg-icons'
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
library.add(fas)
Vue.component('font-awesome-icon', FontAwesomeIcon)
import '@/plugins/fontawesome'
アイコンの使い方:
<font-awesome-icon icon="file-download" />