vue3 メモ ( ref, reactive )

vue3 メモ ( ref, reactive )

2024/05/04 00:00:00
Program
Git-Bash, Node, Vite, Vue, Bootstrap, Sass, SPA, Animate.css

前提 #

vue3 の ref, reactive の違い #

Vue3のrefとreactiveは、どちらもリアクティブなデータを作成するための関数ですが、それぞれに特性と使用場面がある。

  • ref:
    refは基本的な値(数値、文字列など)をリアクティブにする場合に使用。
    refはVueコンポーネント内で一般的に使用され、リアクティブなデータを使用することで、 コンポーネントの状態の変更を監視し、自動的に再レンダリングすることができる。
    また、refはアンラップされるという特性があり、変数の型情報を見るだけでリアクティブなデータであることが認識できる。

    <template>
      <div>{{ count.value }}</div>
    </template>
    
    import { ref } from 'vue';
    const count = ref(0); // Ref<number>
    console.log(count.value); // 0
    
  • reactive:
    reactiveはオブジェクト全体をリアクティブにする場合に使用。
    reactiveはオブジェクトをリアクティブに監視し、そのプロパティの変更を検出して自動的に再レンダリングすることができます。
    しかし、reactiveの返り値の型は元のオブジェクトのままであり、変数の型情報を見ただけではそれが通常のオブジェクトなのか、 リアクティブな値なのか判別できません2。また、reactiveで定義したデータを分割代入するとリアクティブ性が失われるというデメリットがあります。

    <template>
      <div>{{ state.count }}</div>
    </template>
    
    import { reactive } from 'vue';
    const state = reactive({ count: 0 });
    console.log(state.count); // 0
    

vue3 でグローバル変数定義 #

App.vue にグローバル変数を定義する #

<script setup>
import { reactive, provide } from 'vue';
// グローバル変数
const gValues = reactive({
  value: 'test',
});
provide('gValues', gValues);
</script>
  • 読み取り専用の場合
    <script setup>
    import { reactive, readonly, provide } from 'vue';
    // グローバル変数
    const gValues = reactive({
      value: 'test',
    });
    const rgValues = readonly(gValues);
    provide('gValues', rgValues);
    </script>
    

各コンポーネントから参照する #

<template>
  <div>debug:{{gValues.value}}</div>
</template>

<script setup>
import { inject } from 'vue';
const gValues = inject('gValues');
</script>

vue3 でrouterでページ遷移後に指定idまでスクロールさせる #

routerでページ遷移後に指定idまでスクロールさせるには、リンク指定時に/home#xxx のように#指定することで対応可能となる 以下のような href 指定で対応可能

<a class="nav-link" href="/#company" aria-current="page">会社情報</a>

ページ遷移後のスクロールアニメーション指定は以下のrouter.jsに記載する

$ emacs src/router.js

import { createRouter, createWebHistory } from 'vue-router'
import Home from './components/Home.vue'
import About from './components/About.vue'
import Test from './components/Test.vue'

const routes = [
  { path: '/', name: 'Home', component: Home },
  { path: '/About', name: 'About', component: About },
  { path: '/Test', name: 'Test', component: Test },
]

const router = createRouter({
  history: createWebHistory(),
  routes,
  scrollBehavior (to) {  // <-- ここ追加
    // ページ遷移時のアニメーション500(+100)msを待ってid指定位置までスクロールする
    // 以下のsetTimeout指定している理由は、routerを使ったページ遷移時にフェードアニメーションを
    // transitionを使って実現している場合に必要。
    // 時間はフェードアニメーションが500msかかる場合に、念のため100ms余分にまつ
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        if (to.hash) {
          resolve({
            el: to.hash,
            behavior: 'smooth',
          });
        }
      }, 600); // 500ms + 予備100ms 後に実行
    });
  }
})

export default router

以下は、router を使ったページ遷移時のフェードアニメーションの指定方法を示す

  • 通常は router-view 指定のみで遷移可能
  • フェードアニメーションは transition を使って、css でアニメーション内容を指定する

$emacs src/App.vue

<template>
  <div id="app">
    <!-- <router-view /> -->
    <!-- ページ遷移時にフェードアニメーションを実施する(500ms) -->
    <router-view v-slot="{ Component, route }">
      <transition name="fade" mode="out-in">
        <div :key="route.name">  
          <component :is="Component"></component>
        </div>
      </transition>
    </router-view>
  </div>
</template>

<script setup>
import { reactive, provide } from 'vue';
// グローバル変数
const gValues = reactive({
  value: 'test',
});
provide('gValues', gValues);
</script>

<style lang="scss">

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s ease;
}

.fade-enter-from,
.fade-leave-to {
  opacity: 0;
}

</style>

vue3 で transition を使ったページ遷移時のフェードアニメーションとbootstrapのcarouselの組み合わせると動作しない場合の対応 #

以下のような carousel 指定があった場合、script setup で Carousel の cycle を呼び出すことで対応可能となる

<template>
  <div id="carouselTop" class="carousel slide" data-bs-ride="carousel" data-bs-interval="3000">
  ...
</template>

<script setup>
import { onMounted } from 'vue';
import { Carousel } from 'bootstrap';

onMounted(() => {
  let _element = document.querySelector('#carouselTop');
  let _instance = new Carousel(_element);
  _instance.cycle();
});
</script>