LoginSignup
1
4

More than 1 year has passed since last update.

Vue3のライフサイクルフック

Posted at

はじめに(Introduction)

Vueのコードを見る機会がありまして、初期処理をcreatedmountedで行うパターンがあり、どういう状態なのかを調べてみました。

Vueはバージョン3を使用します。(バージョンが異なると名称が異なります。)

ライフサイクルフック(Lifecycle Hooks)

ライフサイクルフックを見てみます。

図( https://v3.ja.vuejs.org/images/lifecycle.svg )には以下8個のフックが記載されています。

beforeCreate
created
beforeMount
mounted
beforeUpdate
updated
beforeUnmount
unmounted

サンプルコード(Sample Code)

各フックにログを入れて状態を確認します。
コードは以下となります、またGithubにもあります。

コード
index.html
<!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>
script.js
'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.counterundefined から 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

カウントが加算されると、beforeUpdateupdatedとイベントが発生します。
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)

重要なのは、createdmountedunmountedのようです。
用途としては以下が考えられると思いました。
createdはHTML反映前にデータなどを更新する場合
mountedはHTML反映後に処理が必要な場合(定期的な処理など)
unmountedは後処理が必要な場合(後ろで動いている処理の停止など)

1
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
4