この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:4
ページ更新者:T
更新日時:2026-06-11 07:07:02

タイトル: $nextTickの使い方(ライフサイクルフック)
SEOタイトル: 【Vue.js】$nextTickの使い方(ライフサイクルフック)

この記事の要点
  • $nextTickDOM 反映後に処理を実行する Vue.js のメソッド
  • data を変更しただけだと DOM はまだ更新されていない
  • this.$nextTick(() => ...) で次の DOM 反映タイミングを待つ
  • Vue 3 Composition API: import { nextTick } from "vue" + await nextTick()
  • 用途: DOM サイズ計算 / scroll 位置調整 / サードパーティライブラリ初期化

 

なぜ nextTick が必要か

Vue は data 変更を検知すると次のティックで DOM を更新します(バッチ処理によるパフォーマンス最適化)。data を変更した直後に DOM を参照しても、まだ更新されていません。

// 例: nextTick なしだと
data() {
    return { message: "" };
},
methods: {
    update() {
        this.message = "Hello";
        // この時点で this.$el.textContent は "" のまま!(DOM はまだ更新されていない)

        const len = this.$el.querySelector("p").textContent.length;
        console.log(len);  // → 0
    }
}

nextTick で DOM 反映を待つ

// Vue 2 / Vue 3 Options API
methods: {
    update() {
        this.message = "Hello";

        this.$nextTick(() => {
            // DOM 反映完了後
            const len = this.$el.querySelector("p").textContent.length;
            console.log(len);  // → 5
        });
    }
}

// async / await でも書ける
methods: {
    async update() {
        this.message = "Hello";
        await this.$nextTick();
        const len = this.$el.querySelector("p").textContent.length;
        console.log(len);
    }
}

Vue 3 Composition API



典型的な使用シーン

① 動的に追加した要素のサイズ計算

async addItem(item) {
    this.items.push(item);  // リストに追加
    await this.$nextTick();
    // 新しい要素の高さを計算
    const newElem = this.$refs.list.lastElementChild;
    const height = newElem.getBoundingClientRect().height;
    console.log("追加した要素の高さ:", height);
}

② スクロール位置の調整

async scrollToBottom() {
    this.messages.push({ text: "新メッセージ" });
    await this.$nextTick();
    // メッセージが描画されてからスクロール
    const container = this.$refs.messageContainer;
    container.scrollTop = container.scrollHeight;
}

③ フォーカス制御

async toggleEditMode() {
    this.editing = true;  // v-if で input 表示
    await this.$nextTick();
    // input が描画されてからフォーカス
    this.$refs.editInput.focus();
}

④ サードパーティライブラリの再初期化

async updateChart() {
    this.chartData = newData;
    await this.$nextTick();
    // Chart.js を再描画
    this.chart.update();
}

async refreshSlider() {
    this.slides = newSlides;
    await this.$nextTick();
    // Swiper を再初期化
    this.swiper.update();
}

watch との組み合わせ

// Vue 3 Composition API
import { watch, nextTick, ref } from "vue";

const items = ref([]);

watch(items, async (newItems) => {
    await nextTick();
    // items が変更されて DOM が更新された後
    console.log("DOM 更新完了");
});

nextTick が複数回ある場合

同じティック内の複数の data 変更は1 回の DOM 更新にまとめられます:

methods: {
    async updateMany() {
        this.a = 1;
        this.b = 2;
        this.c = 3;
        // すべての変更が 1 回の DOM 更新で反映される
        await this.$nextTick();
        // 全部反映済み
    }
}

nextTick の代替

シンプルなケースなら setTimeout(fn, 0)requestAnimationFrame でも近い動作になりますが、Vue の更新サイクルと完全に同期する保証はないため nextTick を使うのが安全:

// ✗ 動くこともあるが、Vue の更新と同期しないことも
this.message = "Hello";
setTimeout(() => {
    console.log(this.$el.textContent);
}, 0);

// ✓ 確実
this.message = "Hello";
this.$nextTick(() => {
    console.log(this.$el.textContent);
});

注意点

無限ループに注意

// ✗ 危険
async update() {
    this.count++;
    await this.$nextTick();
    this.count++;  // また data 変更 → さらに DOM 更新サイクル
    // → updated フックや watcher で意図せず連鎖発火することがある
}

テストでも nextTick

// Vue Test Utils
import { mount } from "@vue/test-utils";
import { nextTick } from "vue";

test("counter increments", async () => {
    const wrapper = mount(Counter);
    await wrapper.find("button").trigger("click");
    await nextTick();  // DOM 反映を待つ
    expect(wrapper.text()).toContain("Count: 1");
});

関連記事