Vue.jsにおける基本的なルーティングコンポーネントの理解

基本的なルーティングコンポーネントの知識

props:親子コンポーネント間(配列、文字列)、子親コンポーネント間(関数)、兄弟コンポーネント間(データを親コンポーネントにマウント)の通信を実現します(読み取り専用)。

カスタムイベント:子親コンポーネント間の通信を可能にします。

グローバルイベントバス$BUS:任意のコンポーネント間の通信を可能にします(Vue 2で重要)。

pubsub:発行/購読パターンを使用して任意のコンポーネント間の通信を実現します(Vueプロジェクトではあまり使われませんが、Reactプロジェクトや微信小程序プロジェクトではよく使われます)。

Vuex:集中式ステート管理コンテナで、任意のコンポーネント間の通信を可能にします(欠点:データは永続化されません)。

ref:親コンポーネントから子コンポーネントのインスタンスVCを取得し、子コンポーネントのリアクティブなデータとメソッドにアクセスします。

slot:スロット(デフォルトスロット、名前付きスロット、スコープスロット)を使用して親子コンポーネント間の通信を実現します。

1. propsによるルーティングコンポーネント

基本的な知識:1. プロジェクトの実行:ターミナルで `npm run dev` を入力します。2. Vueファイルテンプレートの自動生成方法:ファイル -> 事前設定 -> ユーザースニペット -> vue.json を入力 -> コードを入力します。

  {
    "Vue Component Template": {
      "prefix": "vue",
      "body": [
        "<template>",
        "  <div>",
        "    <!-- Component HTML goes here -->",
        "  </div>",
        "</template>",
        "",
        "<script>",
        "export default {",
        "  name: '$1',",
        "  data() {",
        "    return {",
        "      // component data",
        "    };",
        "  },",
        "  methods: {",
        "    // component methods",
        "  }",
        "};",
        "</script>",
        "",
        "<style scoped>",
        "/* component CSS styles */",
        "</style>"
      ],
      "description": "Basic Vue component structure"
    }
  }
  

props: 親子コンポーネント間の通信を実現します。propsのデータは読み取り専用です!

1.1 親コンポーネントからのパラメータの受け渡し

親コンポーネント内でインポートを記述します:`import Child from './Child.vue';` div内に`<child></child>`を記述します。 コンポーネント間の通信は属性形式で行われます。

1. 親コンポーネントから子コンポーネントへの文字列の伝達:

<child info="私は曹操"></child>

2. 組み合わせAPI関数を使用して動的にデータを伝達します。

  import { ref } from 'vue';
  let money = ref(10000);
  <child info="私は曹操" :money="money"></child>
  

前者のデータ伝達は固定的ですが、後者は柔軟です。

1.2 子コンポーネントでのデータ受信

1. オプションAPI書き方

  // export default {  
  // props: ['info', 'money']  
  // };
  <p>{{ info }}</p>
  

2. 組み合わせAPI書き方 setup

  // definePropsはVue 3で提供されるメソッドで、インポート不要
  let props = defineProps(['info', 'money']);
  <p>{{ props.info }}</p>
  <p>{{ $props.money }}</p>
  <p>{{ info }}</p>
  <p>{{ money }}</p>
  

プロキシオブジェクトの配列propsは変更できません。変更が必要な場合は、親コンポーネント内で変更します。

2. カスタムイベント

2.1 ネイティブDOMイベント

ユーザーがウェブページと対話する際のマウスクリックなどの方法があります。

  <button @click="handler1(1, 2, 3, $event)">クリックして複数のパラメータを伝達</button>
  <Event1 @click="handler2"></Event1>
  
  // サブコンポーネントのインポート
  import Event1 from './Event1.vue';
  const handler = (event) => {
    console.log(event);
  }
  const handler1 = (a, b, c, $event) => {
    console.log(a, b, c, $event);
  }
  const handler2 = () => {
    console.log(123);
  }
  

2.2 カスタムイベント

コンポーネント間の通信を実現し、子コンポーネントから親コンポーネントへパラメータを伝達します。

  <Event2 @xxx="handler3" @click="handler4"></Event2>
  
  // サブコンポーネントのインポート
  import Event2 from './Event2.vue';
  const handler3 = (param1, param2) => {
    console.log(param1, param2);
  }
  const handler4 = (param1, param2) => {
    console.log(param1, param2);
  }
  

Event2.vue

  <template>
    <div class="child">
      <p>私は子コンポーネント2です</p>
      <button @click="handler">クリックしてカスタムイベントをトリガー</button>
      <button @click="$emit('click', 'AK47', 'J20')">クリックしてカスタムイベントclickをトリガー</button>
    </div>
  </template>

  <script setup lang="ts">
  let $emit = defineEmits(['xxx']);

  const handler = () => {
    $emit('xxx', '東風ミサイル', '空母');
  }
  </script>

  <style scoped>
  .child {
    width: 400px;
    height: 200px;
    background-color: pink;
  }
  </style>
  

3. グローバルイベントバス

グローバルイベントバスは任意のコンポーネント間の通信を可能にします。Vue 2ではVMとVCの関係からグローバルイベントバスを導出できますが、Vue 3ではVueコンストラクタがないため、mittプラグインを使用します。

例:兄弟コンポーネント間の通信

1. bus/index.tsを作成してbusオブジェクトをカプセル化します。

  import mitt from "mitt";
  const $bus = mitt();
  export default $bus;
  

2. 兄弟コンポーネント2にイベントをバインドします。

  <script setup lang="ts">
  import $bus from '../../bus';
  import { onMounted } from 'vue';

  onMounted(() => {
    $bus.on('car', (car) => {
      console.log(car);
    });
  })
  </script>
  

3. 兄弟コンポーネント1がイベントをトリガーします。

  <template>
    <div class="child2">
      <h1>私は子コンポーネント2: 曹丕</h1>
      <button @click="handler">クリックして兄弟に車を送る</button>
    </div>
  </template>

  <script setup lang="ts">
  import $bus from '@/bus';
  const handler = () => {
    $bus.emit('car', { car: "フェラーリ" });
  }
  </script>

  <style scoped>
  .child2 {
    width: 300px;
    height: 300px;
    background-color: skyblue;
  }
  </style>
  

4. v-model

v-modelを使用して親子コンポーネント間のデータ同期を実現します。

子コンポーネント

  <template>
    <div class="child">
      <h3>金額: {{ modelValue }}</h3>
      <button @click="handler">親子コンポーネント間のデータ同期</button>
    </div>
  </template>

  <script setup lang="ts">
  let props = defineProps(['modelValue']);
  let $emit = defineEmits(['update:modelValue']);

  const handler = () => {
    $emit('update:modelValue', props.modelValue + 1000);
  }
  </script>

  <style scoped>
  .child {
    width: 600px;
    height: 300px;
    background-color: skyblue;
  }
  </style>
  

親コンポーネント

  <template>
    <div>
      <h1>v-model: 金額: {{ money }}</h1>
      <input type="text" v-model="info">
      <hr>
      <Child :modelValue="money" @update:modelValue="handler"></Child>
    </div>
  </template>

  <script setup lang="ts">
  import { ref } from 'vue';
  import Child from './Child.vue';

  let info = ref('');
  let money = ref(10000);

  const handler = (num: any) => {
    money.value = num;
  }
  </script>

  <style scoped></style>
  

5. useAttrs

useAttrsを使用してコンポーネントの属性とイベントを取得します。

例:el-buttonコンポーネントを再ラッピングし、マウスを置くとテキストが表示されます。

  <el-button type="primary" size="small" :icon="Edit"></el-button>
  <HintButton type="primary" size="small" :icon="Edit"></HintButton>
  

type="primary" size="small" :icon="Edit"はpropsとして扱われ、子コンポーネントが受け取ります。

  // useAttrsを使用して属性とイベントを取得
  import { useAttrs } from 'vue';
  let $attrs = useAttrs();
  console.log($attrs);
  

ビュー表示

  <el-button :="$attrs"></el-button>
  <div :title="title"></div>
  

useAttrsはイベントも受け取ることができます。

6. ref と $parent

ref: 実際のDOMノードを取得し、子コンポーネントのインスタンスVCを取得します。

$parent: 子コンポーネント内で親コンポーネントのインスタンスを取得します。

例:親コンポーネントにボタンを設置し、親の金額を+10、子の金額を-10します。

  <Son ref="son"></Son>
  
  let son = ref();
  

子コンポーネントの具体的なデータにはアクセスできないため、子コンポーネント内でメソッドを公開します。

  defineExpose({
    money,
    fly
  });
  

子コンポーネントのインスタンスを取得し、データとメソッドを使用します。

  const handler = () => {
    money.value += 10;
    son.value.money -= 10;
    son.value.fly();
  }
  

7. provide と inject

Vue 3はprovide(提供)とinject(注入)を提供し、隔世コンポーネント間のデータ伝達を可能にします。

  provide('TOKEN', car);
  

孫コンポーネント(息子または孫でも使用可)

  import { inject } from 'vue';
  let car = inject('TOKEN');
  const updateCar = () => {
    car.value = '自転車';
  }
  

孫コンポーネントは直接祖父コンポーネントから渡されたデータを変更できます。

8. PiniaのオプションAPI

Vue 2では通常、Vuex集中型ステート管理コンテナを使用して任意のコンポーネント間の通信を実現します。Vue 3ではPiniaを使用します。

Piniaの書き方は2種類あり、オプションAPIと組み合わせAPIがあります。

store/index.tsを作成して大規模なストアを作成します。

  import { createPinia } from "pinia";
  let store = createPinia();
  export default store;
  

エントリーポイントmain.tsでストアをインポートします。

  import store from './store';
  app.use(store);
  

小さなストアstore/modules/info.tsを作成します。

  import { defineStore } from "pinia";

  let useInfoStore = defineStore("info", {
    state: () => {
      return {
        count: 99,
        arr: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
      }
    },
    actions: {
      updateNum(a: number, b: number) {
        this.count++;
      }
    },
    getters: {
      total() {
        let result: any = this.arr.reduce((prev: number, next: number) => {
          return prev + next;
        }, 0);
        return result;
      }
    }
  });

  export default useInfoStore;
  

倉庫データの更新方法:

  <button @click="updateCount">クリックして倉庫データを更新</button>
  
  const updateCount = () => {
    infoStore.updateNum(66, 77);
  }
  

gettersメソッドはデータを簡略化し、計算します。

  getters: {
    total() {
      let result: any = this.arr.reduce((prev: number, next: number) => {
        return prev + next;
      }, 0);
      return result;
    }
  }
  

reduce()メソッドの詳細については、以下のリンクを参照してください。

https://blog.csdn.net/w17624003437/article/details/125858710

9. Piniaの組み合わせAPI

Piniaの組み合わせAPIについても同様に適用できます。

タグ: vue.js props Custom Events Global Event Bus pubsub

8月6日 04:28 投稿