はじめに(Introduction)
Vueのコードを見る機会がありまして、初期処理をcreated
とmounted
で行うパターンがあり、どういう状態なのかを調べてみました。
Vueはバージョン3を使用します。(バージョンが異なると名称が異なります。)
ライフサイクルフック(Lifecycle Hooks)
ライフサイクルフックを見てみます。
図( https://v3.ja.vuejs.org/images/lifecycle.svg )には以下8個のフックが記載されています。
beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeUnmount
unmounted
サンプルコード(Sample Code)
各フックにログを入れて状態を確認します。
コードは以下となります、またGithubにもあります。
コード
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>VUE 3 - Life Cycle</title>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="https://unpkg.com/vue@next"></script>
<script src="script.js"></script>
</head>
<body>
<div id="counter">
<div id="cnt" v-text="counter"></div>
</div>
</body>
</html>
'use strict';
var app = null;
function init() {
console.log('Vue.version', Vue.version);
app = Vue.createApp(LifeCycle);
let vm = app.mount('#counter');
console.log(app);
console.log(vm);
}
const LifeCycle = {
data() {
return {
counter: 0,
intervalID: null,
}
},
beforeCreate() {
console.log('>>> beforeCreate');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< beforeCreate');
},
created() {
console.log('>>> created');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< created');
},
beforeMount() {
console.log('>>> beforeMount');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< beforeMount');
},
mounted() {
console.log('>>> mounted');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< mounted');
this.intervalID = setInterval(() => {
console.log('count');
this.counter++;
if (this.counter > 2) {
app.unmount();
}
}, 1000)
},
beforeUpdate() {
console.log('>>> beforeUpdate');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt').innerText);
console.log('<<< beforeUpdate');
},
updated() {
console.log('>>> updated');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt').innerText);
console.log('<<< updated');
},
beforeUnmount() {
console.log('>>> beforeUnmount');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< beforeUnmount');
},
unmounted() {
console.log('>>> unmounted');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< unmounted');
if (this.intervalID) {
clearInterval(this.intervalID);
}
},
}
window.addEventListener('load', init);
実行結果(Execution Result)
各ライフライクルでどういう変化が起こっているのかを観察します。
beforeCreate & created
beforeCreate() {
console.log('>>> beforeCreate');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< beforeCreate');
},
created() {
console.log('>>> created');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< created');
},
>>> beforeCreate
undefined
null
null
<<< beforeCreate
>>> created
0
null
null
<<< created
this.counter
が undefined
から 0
に変更されています。
自身にdata
が適用されたようです。
DOMはまだ作成されていません。
beforeMount & mounted
beforeMount() {
console.log('>>> beforeMount');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< beforeMount');
},
mounted() {
console.log('>>> mounted');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< mounted');
this.intervalID = setInterval(() => {
console.log('count');
this.counter++;
if (this.counter > 2) {
app.unmount();
}
}, 1000)
},
>>> beforeMount
0
null
null
<<< beforeMount
>>> mounted
0
<div id="cnt">0</div>
<div id="cnt">0</div>
<<< mounted
this.$el
に テンプレートが適用されています。
mounted
で1秒毎にカウントを加算するインターバルを設定します。
beforeUpdate & updated
mounted
で設定したインターバルでカウントが加算されると、更新のイベントが発生します。
beforeUpdate() {
console.log('>>> beforeUpdate');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt').innerText);
console.log('<<< beforeUpdate');
},
updated() {
console.log('>>> updated');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt').innerText);
console.log('<<< updated');
},
count
>>> beforeUpdate
1
<div id="cnt">1</div>
0
<<< beforeUpdate
>>> updated
1
<div id="cnt">1</div>
1
<<< updated
count
>>> beforeUpdate
2
<div id="cnt">2</div>
1
<<< beforeUpdate
>>> updated
2
<div id="cnt">2</div>
2
<<< updated
カウントが加算されると、beforeUpdate
、updated
とイベントが発生します。
this.counter
が加算されており、this.$el
も更新されている状態となります。
しかし、HTMLの値は、beforeUpdate
ではカウントの加算前、update
で加算後の値となっています。
ちなみにDOMはthis.$el
と同じでした。
beforeUnmount & unmounted
mounted
で設定したインターバルはカウントが2を超えると、app.unmount();
を行いunmount
処理が始まります。
beforeUnmount() {
console.log('>>> beforeUnmount');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< beforeUnmount');
},
unmounted() {
console.log('>>> unmounted');
console.log(this.counter);
console.log(this.$el);
console.log(document.getElementById('cnt'));
console.log('<<< unmounted');
if (this.intervalID) {
clearInterval(this.intervalID);
}
},
count
>>> beforeUnmount
3
<div id="cnt">2</div>
<div id="cnt">2</div>
<<< beforeUnmount
>>> unmounted
3
<div id="cnt">2</div>
null
<<< unmounted
beforeUnmount
ではカウントは加算後の値、this.$el
とDOMは更新されていない状態となります。
unmounted
でDOMが削除されています。
コンソールログ
Console log 全文
Navigated to file:///C:/Users/marba/Desktop/work/education/vue3/index.html
vue@next:10907 You are running a development build of Vue.
Make sure to use the production build (*.prod.js) when deploying for production.
script.js:6 Vue.version 3.2.4
script.js:21 >>> beforeCreate
script.js:22 undefined
script.js:23 null
script.js:24 null
script.js:25 <<< beforeCreate
script.js:28 >>> created
script.js:29 0
script.js:30 null
script.js:31 null
script.js:32 <<< created
script.js:35 >>> beforeMount
script.js:36 0
script.js:37 null
script.js:38 null
script.js:39 <<< beforeMount
script.js:42 >>> mounted
script.js:43 0
script.js:44 <div id="cnt">0</div>
script.js:45 <div id="cnt">0</div>
script.js:46 <<< mounted
script.js:9 {_uid: 0, _component: {…}, _props: null, _container: div#counter, _context: {…}, …}
script.js:10 Proxy {…}
script.js:48 count
script.js:56 >>> beforeUpdate
script.js:57 1
script.js:58 <div id="cnt">1</div>
script.js:59 0
script.js:60 <<< beforeUpdate
script.js:63 >>> updated
script.js:64 1
script.js:65 <div id="cnt">1</div>
script.js:66 1
script.js:67 <<< updated
script.js:48 count
script.js:56 >>> beforeUpdate
script.js:57 2
script.js:58 <div id="cnt">2</div>
script.js:59 1
script.js:60 <<< beforeUpdate
script.js:63 >>> updated
script.js:64 2
script.js:65 <div id="cnt">2</div>
script.js:66 2
script.js:67 <<< updated
script.js:48 count
script.js:70 >>> beforeUnmount
script.js:71 3
script.js:72 <div id="cnt">2</div>
script.js:73 <div id="cnt">2</div>
script.js:74 <<< beforeUnmount
script.js:77 >>> unmounted
script.js:78 3
script.js:79 <div id="cnt">2</div>
script.js:80 null
script.js:81 <<< unmounted
まとめ(Conlution)
重要なのは、created
、mounted
、unmounted
のようです。
用途としては以下が考えられると思いました。
created
はHTML反映前にデータなどを更新する場合
mounted
はHTML反映後に処理が必要な場合(定期的な処理など)
unmounted
は後処理が必要な場合(後ろで動いている処理の停止など)