The “composite API” is a new syntax extended to Vue3. The syntax explained in the previous basic lesson is called” option API”. Both apis are supported in VUe3.

What does it solve?

Combination of the API“You can split it even further.”Option APIIn the”JS logic.can put a certain logical”Data/computed/watch/methods/hook statement cycle“Wrapped in a separate function (or file). The split function is usually named “useXxx”.

Breaking down actual requirements

Analyzing the shopping cart module below, I plan to put the JS partSplit into 2 parts (function): One is used to get the shopping cart item data and the total price, and one is used to calculate the coupon and the total price after the discount. Subtables are functions:useGetCart“And”useCoupon“.

The setup structure

The old “options API” does not have the “methods” field, but it can also encapsulate functions. Let’s look at the code format of the” composition API”. A new field, “setup”, is the signature property of the “composition API”, which is a function. The return value is recognized and rendered by the template, similar to “data”.

Pay special attention to the return values of the two functions, which return data (similar to data) and functions (similar to methods). The actual function contains a separate “watch/computed/ lifecycle hook “that groups the contents of a VUE component’s “data” and “methods”, which is why it is called a” composite API”.

<template>
  <article v-if="cart.length > 0">
    <ul>
      <li v-for="item in cart" :key="item.name">{{item.name}} : {{item.price}} element<input v-model="item.count" type="number" style="width: 48px" />
      </li>
    </ul>
    <h5 style="margin-left: 100px">Price :{{totalPrice}} yuan</h5>
    <h5 style="margin-left: 100px; color: #f10">Total price :{{realTotalPrice}} yuan</h5>
    <button @click="createOrder">pay</button>
  </article>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  name: 'Cart'.setup(){
    // Shopping cart details and total price
  	const [cart,totalPrice,createOrder] = useGetCart();
    
    // Discount price
    const realTotalPrice = useCoupon();
    
    // Returns the data identified by the template, as defined by data
    return{cart,totalPrice,realTotalPrice,createOrder}; }});</script>
Copy the code

Internal implementation of “useXxx” function

This “use” as a prefix for function names is a naming convention, and there are no actual restrictions on naming. For every “watch/computed/ lifecycle hook “in a function, they all appear as functions.

import {computed} from 'vue';
/** * get shopping cart details */
function useGetCart() {
  // Shopping cart details (reactive)
  const cart = reactive<{ name: string; count: number; price: number} [] > ([]);// Simulate an asynchronous request
  setTimeout(() = > {
    cart.push(
      { name: The word "apple".count: 10.price: 10 },
      { name: "Banana".count: 20.price: 20}); },1000);

  // Total price (computed)
  const totalPrice = computed(() = > {
    return cart.reduce((total, item) = > item.count * item.price + total, 0);
  });

  return [cart, totalPrice] as const;
}
Copy the code

There’s a new function called ref, which is used to “define the response data,” and we’re going to talk about what ref is.

Pay attention to

  1. “As const” means to assert that the array type is a primitive, so if you forgot the TS part, you might want to review ts before we move on.
  2. Mounted => onMounted

Define response data (Reactive/REF)

“Response data” is the data that changes in value can drive changes in the DOM, and the data we defined earlier in “data” is the response data. But in “setup” if we want to define data, there is no “data” function. Instead, there is a” reactive/ref” function:

reactive

Defines the response data, the input can only be the object type, and returns the response version of the input object.

<template>
    <h1>{{count}}</h1>
</template>

<script lang="ts">
import { defineComponent } from "vue";
export default defineComponent({
  setup(){
    return reactive({count:99}); }});</script>
Copy the code

The actualI don’t need to be reactive in this case, the result is the same, but if the “count” data is changed, then the interface will not automatically change, it will always display “99”.

ref

Reactive: Reactive: reactive: reactive: reactive: reactive: reactive: reactive: reactive: reactive: reactive: reactive

const n = ref(110);
console.log(n);
Copy the code

Can see the return value in the value field, do so because the data changes in js monitoring only supports the “reference data type”, for the string and number type if you need to monitor need to construct an object, so this ref internal need to construct a {110} value: variable.​

Reactive and REF selection

Important: Use Reactive if the data to be monitored is object, and ref if it is primitive (number/ Boolean /string).

Encapsulating functions (useXxx)

Now let’s go back to the implementation of two functions.

useGetCart

Returns the item information in the shopping cart and the total price, which uses a “computed property” function (computed property) and a “generate order” function encapsulated because it needs the item information in the shopping cart as a parameter, so we use 2 as a group.

import {computed} from 'vue';
/** * get shopping cart details */
function useGetCart() {
  // Shopping cart details (reactive)
  const cart = reactive<{ name: string; count: number; price: number} [] > ([]);// Simulate an asynchronous request
  setTimeout(() = > {
    cart.push(
      { name: The word "apple".count: 10.price: 10 },
      { name: "Banana".count: 20.price: 20}); },1000);

  // Total price (computed)
  const totalPrice = computed(() = > {
    return cart.reduce((total, item) = > item.count * item.price + total, 0);
  });
  
  
  // Generate order (methods)
  function createOrder(){
  	// Simulate order generation
    setTimeout(() = >{
    	console.log('Successful purchase${cart.length}Goods `);
    },1000)}return [cart, totalPrice,createOrder] as const;
}
Copy the code

useCoupon

Get the discount amount, and return to calculate the discount amount. Use watch to monitor the “total price “, recalculate the” total price after discount “when it changes, and use “onMounted” to control the timing of data request triggering (this example is not useful, only to demonstrate the use of “onMounted”).

import {watch,onMounted} from 'vue';
/** ** get coupon */
function useCoupon(totalPrice: Ref<number>) {
  const realTotalPrice = ref(0);
  // Instead of using onMouted,
  // Just to demonstrate usage
  onMounted(() = > {
    // Simulate an asynchronous request
    setTimeout(() = > {
      const coupon = 9;
      watch(
        totalPrice,
        (value) = > {
          realTotalPrice.value = value - coupon;
        },
        { immediate: true}); },1000);
  });

  return realTotalPrice;
}
Copy the code

As a function, the second parameter of “watch” is an object, with the field “immediate” indicating that the callback is initialized and run, and “deep” indicating the depth monitoring data (Object).

Complete source code

Github.com/any86/vue3-…

WeChat group

Thank you for your reading. If you have any questions, you can add me to the wechat group, and I will pull you into the wechat group (Because Tencent limits the number of wechat groups to 100, when the number exceeds 100, you must be joined by group members).

To be continued

Please follow me for updates