LoginSignup
0
1

More than 3 years have passed since last update.

Vue3のComposition APIについての学習

Posted at

概要

以下の動画の文字起こし&理解の整理
https://www.youtube.com/watch?v=XIpQLdcqawc

Composition APIとは

柔軟にコンポーネントをかける

なぜ使うのか

  • 保守性の向上
  • 再利用性の向上

Vue2 -> Vue3

Vue2で書かれたコード

// src/components/CounterMouse.vue
<template>
  <div @mousemove="updateMouse">
    <div>
      Count is {{ count }}, count * {{ times }} is {{ multiplicationResult }}
      <button @click="increment">
        +
      </button>
    </div>
    <div>Mouse is at {{ mousePosition.x }}, {{ mousePosition.y }}</div>
  </div>
</template>

<script>
export default {
  props: {
    times: {
      type: Number,
      default: 2
    }
  },
  data() {
   return {
      mousePosition: {
      x: 0,
      y: 0
    },
    count: 0
   }
  },
  computed: {
    multiplicationResult() {
      return this.count * this.times;
    }
  },
  watch: {
    count() {
      setTimeout(() => {
        alert('3 seconds have passed since the value changed');
      }, 3000);
    }
  },
  methods: {
    increment() {
      this.count += 1;
    },
    updateMouse(event) {
      this.mousePosition.x = event.clientX
      this.mousePosition.y = event.clientY
    },
  }
}
</script>

Vue3で書き換えたコード

// src/components/CounterMouse.vue
<template>
  <div @mousemove="updateMouse">
    <div>
      <!-- you can omit ".value" to get the value in template -->
      Count is {{ count }}, count * {{ times }} is {{ multiplicationResult }}
      <button @click="increment">
        +
</template>

<script>
// "reactive" can be passed only object as argument
// "ref" can be passed not only object such as Number, String, and so on
// you should access the value with ".value" if you use "ref"
import { reactive, ref, computed, watch } from '@vue/composition-api';
export default {
  props: {
    times: {
      type: Number,
      default: 2
    }
  },
  // "setup" is executed before "beforeCreate"
  // That's why "this" cannot be used
  // "setup" has first argument of props
  setup(props) {
    // data
    const mousePosition = reactive({
      x: 0,
      y: 0
    });
    let count = ref(0);

    // methods
    const increment = () => {
      count.value += 1;
    };
    const updateMouse = (event) => {
      mousePosition.x = event.clientX
      mousePosition.y = event.clientY
    };

    // computed
    const multiplicationResult = computed(() =>  {
      return count.value * props.times;
    });

    // watcher
    watch(count, () => {
      setTimeout(() => {
        alert('3 seconds have passed since the value changed');
      }, 3000)
    })

    return {
      mousePosition,
      count,
      increment,
      updateMouse,
      multiplicationResult
    }
  },
}
</script>

補足

reactiveとは

仮に以下のようなコードがあった時、依存関係のあるものが変更された時に更新される状態をreactiveと呼ぶ
つまり、xが変化すれば、aの値も変化する状態

let x = 1;

let a = x + 3;

x = 3;

a is 4? or 6? 

保守性をあげる(見やすくする)

// src/components/CounterMouse.vue
  :
  :
  setup(props) {
    // Processing for "count"
    let count = ref(0);
    const increment = () => {
      count.value += 1;
    };
    const multiplicationResult = computed(() =>  {
      return count.value * props.times;
    });
    watch(count, () => {
      setTimeout(() => {
        alert('3 seconds have passed since the value changed');
      }, 3000)
    })

    // Processing for "mousePosition"
    const mousePosition = reactive({
      x: 0,
      y: 0
    });
    const updateMouse = (event) => {
      mousePosition.x = event.clientX
      mousePosition.y = event.clientY
    };

    return {
      mousePosition,
      count,
      increment,
      updateMouse,
      multiplicationResult
    }
  },
}

Vue2はオプションごとにまとまっているが、機能ごとにまとめることができる

再利用性をあげる

Vue2でのmixinは処理を追うのを難しくさせる場合があるのと、名前のコンフリクトが起こる可能性がある

// src/components/CounterMouse.vue
:
:
import { ref, computed, watch } from '@vue/composition-api';
import { usePosition } from '../util-functions/position'

export default {
    :
    :
    // Processing for "mousePosition"
    // const mousePosition = reactive({
    //   x: 0,
    //   y: 0
    // });
    // const updateMouse = (event) => {
    //   mousePosition.x = event.clientX
    //   mousePosition.y = event.clientY
    // };

    // you can change names to avoid names confliction
    const { position: mousePosition, updatePosition: updateMouse } = usePosition();

    return {
      :
      :
      multiplicationResult
    }
  },
}
// src/util-functions/position.js
import { reactive } from '@vue/composition-api'

export const usePosition = () => {
  const position = reactive({
    x: 0,
    y: 0
  });

  const updatePosition = (event) => {
    position.x = event.clientX
    position.y = event.clientY
  };

  return { position, updatePosition }
}

最終的なコード


<template>
  <div @mousemove="updateMouse">
    <div>
      <!-- you can omit ".value" to get the value in template -->
      Count is {{ count }}, count * {{ times }} is {{ multiplicationResult }}
      <button @click="increment">
        +
      </button>
    </div>
    <div>Mouse is at {{ mousePosition.x }}, {{ mousePosition.y }}</div>
  </div>
</template>

<script>
// "reactive" can be passed only object as argument
// "ref" can be passed not only object such as Number, String, and so on
// you should access the value with ".value" if you use "ref"
import { ref, computed, watch } from '@vue/composition-api';
import { usePosition } from '../util-functions/position'

export default {
  props: {
    times: {
      type: Number,
      default: 2
    }
  },
  // "setup" is executed before "beforeCreate"
  // That's why "this" cannot be used
  // "setup" has first argument of props
  setup(props) {
    // Processing for "count"
    let count = ref(0);
    const increment = () => {
      count.value += 1;
    };
    const multiplicationResult = computed(() =>  {
      return count.value * props.times;
    });
    watch(count, () => {
      setTimeout(() => {
        alert('3 seconds have passed since the value changed');
      }, 3000)
    })

    // Processing for "mousePosition"
    const { position: mousePosition, updatePosition: updateMouse } = usePosition()

    return {
      mousePosition,
      count,
      increment,
      updateMouse,
      multiplicationResult
    }
  },
}
</script>

0
1
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
0
1