Vueのv3を使っていて、下のエラーが出ている場合の対処方法です。
結論から書くと、このエラーの原因はVue 3のプロジェクトでVue 2用のプラグイン@vue/composition-apiをimportしていることです。Vue 3ではComposition APIが本体に組み込まれているので、defineComponentやref、onMountedはすべて'vue'からimportすれば解決します。
エラー内容
vue-composition-api.esm.js?a6f4:64 Uncaught (in promise)
TypeError: Cannot read property 'util' of undefined
合わせて下の警告が出ました。
[Vue warn]: Unhandled error during execution of scheduler flush.
This is likely a Vue internals bug.
Please open an issue
at https://new-issue.vuejs.org/?repo=vuejs/vue-next
at <Home onVnodeUnmounted=fn<onVnodeUnmounted>
ref=Ref< undefined > >
エラーが出たscriptタグ
<script>
import { defineComponent, onMounted } from '@vue/composition-api'
import { ref } from '@vue/reactivity'
export default defineComponent({
setup() {
const aaa = ref(null);
const bbb = ref(null);
const ccc = ref(null);
function handleScroll() {
...
}
onMounted(() => {
...
});
return {
aaa,
bbb,
ccc,
}
},
})
</script>
解決方法
// import { defineComponent, onMounted } from '@vue/composition-api'
// import { ref } from '@vue/reactivity'
import { defineComponent, onMounted, ref } from 'vue'
importする先をvueにすれば解決します。refも同様で、@vue/reactivityから直接importする必要はありません。
直ったら、不要になったパッケージも外しておきます。
npm uninstall @vue/composition-api
なぜこのエラーになるのか
@vue/composition-apiは、Vue 2.6以前でComposition APIを先取りするためのプラグインです。内部でVue 2のグローバルなVue.utilを参照しているため、Vue 3のインスタンスに対して動かすとutilがundefinedになり、このエラーが出ます。
バージョン別の正しいimport先は次のとおりです。
- Vue 3:
import { ref, onMounted } from 'vue' - Vue 2.7:Composition APIが本体に同梱されたため、同じく
'vue'からimport - Vue 2.6以前:
@vue/composition-apiをプラグインとしてVue.use()で登録してからimport
古い記事やサンプルをVue 3のプロジェクトにコピーしたときに起きやすいので、import文のfromの部分を最初に確認してください。Vue 3のComposition APIで実際にrefやonMountedを使う例は、Vue 3 Composition APIでクリップボードにコピーする方法と、同じくスクロールイベントを扱う「トップへ戻る」ボタンの作り方を参考にしてください。