Présentation de la fonction @vue/composition-api

avant-propos

@vue/composition-api fournit des capacités de programmation fonctionnelles similaires à l'API de composition Vue3 pour Vue2 (inclus avec 2.7, disponible pour 2.6 et inférieur) via un plug-in. Ses idées de mise en œuvre comprennent principalement :

1. Fournir une fonction combinée pour suivre les dépendances réactives à l'intérieur de la fonction.

2. Enregistrez l'état réactif généré par la combinaison dans l'instance du composant et restaurez-le lors du rendu.

3. Réécrivez le crochet de cycle de vie du composant et restaurez le contexte de la fonction composite dans la fonction de crochet.

Utilisez la fonction setup() comme point d'entrée pour exécuter chaque API réactive afin de suivre les dépendances pendant son exécution, de former un état réactif, puis de l'enregistrer dans l'instance ; modifiez le contexte d'exécution dans le crochet de cycle de vie et exécutez la fonction combinée à nouveau pour restaurer l'état réactif afin d'obtenir une expérience de programmation similaire à Vue3.

Pourquoi avez-vous besoin de l'API de composition

Option API Vue2 traditionnelle

Prenons todolist comme exemple pour voir un cas d'OptionAPI basé sur vue2 :

<template>
  <div class="hello">
    <h1>{
   
   { msg }}</h1>
    <input
      class="add-todo"
      v-focus
      type="text"
      placeholder="add something"
      v-model="newTodo"
      @keyup.enter="addTodo"
    />
    <div v-for="todo in todoList" :key="todo.id" class="todo-row">
      <input type="checkbox" v-model="todo.completed" />
      <div v-if="!todo.editing" @dblclick="editTodo(todo)">
        {
   
   { todo.title }}
      </div>
      <input
        v-else
        type="text"
        v-model="todo.title"
        @blue="doneEdit(todo)"
        @keyup.enter="doneEdit(todo)"
        @keyup.esc="cancelEdit(todo)"
      />
    </div>
  </div>
</template>

<script lang="ts">
import Vue from "vue";
import {
      
      
  reactive,
  ref,
  computed,
  onMounted,
  ComputedRef,
} from "@vue/composition-api";

type Todo = {
      
      
  id: number;
  completed: boolean;
  editing: boolean;
  title: string;
};
export default Vue.extend({
      
      
  name: "HelloWorld",
  props: {
      
      
    msg: String,
  },
  mounted() {
      
      
    console.warn(`component mounted..`);
  },
  data() {
      
      
    return {
      
      
      todoList: [
        {
      
      
          id: 1,
          title: "hello",
          completed: false,
          editing: false,
        },
        {
      
      
          id: 2,
          title: "world",
          completed: false,
          editing: false,
        },
      ],
      newTodo: undefined as undefined | string,
    };
  },
  computed: {
      
      
    getLatestTodoId(): number {
      
      
      const lastTodo: Todo = this.todoList[this.todoList.length - 1];
      return lastTodo.id;
    },
  },

  methods: {
      
      
    addTodo() {
      
      
      if (this.newTodo === undefined) return;
      this.todoList.push({
      
      
        id: this.getLatestTodoId + 1,
        title: this.newTodo,
        completed: false,
        editing: false,
      });
    },

    editTodo(todo: Todo) {
      
      
      todo.editing = !todo.editing;
    },

    cancelEdit(todo: Todo) {
      
      
      const editingTodo: Todo | undefined = this.todoList.find(
        (todo: Todo) => todo.editing === true
      );
      if (editingTodo === undefined) return;
      editingTodo.editing = false;
    },

    doneEdit(todo: Todo) {
      
      
      const editingTodo: Todo | undefined = this.todoList.find(
        (todo: Todo) => todo.editing === true
      );
      if (editingTodo === undefined) return;
      editingTodo.title = todo.title;
      editingTodo.editing = false;
    },
  },
  directives: {
      
      
    focus: {
      
      
      inserted(el) {
      
      
        el.focus();
      },
    },
  },
});
</script>

Amélioration de l'API de composition de configuration de Vue2

Le cas de la transformation en @vue/composition-api :

<template>
  <div class="hello">
    <section style="margin-bottom:32px;">
      <h1 v-if="show">{
   
   { msg }}</h1>
      <button @click="toggle">Toggle above to hide</button>
    </section>
    <input
      class="add-todo"
      v-focus
      type="text"
      placeholder="add something"
      v-model="state.newTodo"
      @keyup.enter="addTodo"
    />
    <div v-for="todo in state.todoList" :key="todo.id" class="todo-row">
      <input type="checkbox" v-model="todo.completed" />
      <div v-if="!todo.editing" @dblclick="editTodo(todo)">
        {
   
   { todo.title }}
      </div>
      <input
        v-else
        type="text"
        v-model="todo.title"
        @blur="doneEdit(todo)"
        @keyup.enter="doneEdit(todo)"
        @keyup.esc="cancelEdit(todo)"
        v-focus
      />
    </div>
  </div>
</template>

<script lang="ts">
import Vue from "vue";

import {
      
       totoListLogic } from "@/compositions/todoListLogic";
import {
      
       toggleLogic } from "@/compositions/toggleLogic";

export default Vue.extend({
      
      
  name: "HelloWorld",
  props: {
      
      
    msg: String,
  },
  setup() {
      
      
    // todo business logic
    const {
      
      
      state,
      getLatestTodoId,
      addTodo,
      editTodo,
      cancelEdit,
      doneEdit,
    } = totoListLogic();

    // toggle business logic
    const {
      
       show, toggle } = toggleLogic();

    return {
      
      
      state,
      addTodo,
      editTodo,
      doneEdit,
      cancelEdit,
      show,
      toggle,
    };
  },
  directives: {
      
      
    focus: {
      
      
      inserted(el) {
      
      
        el.focus();
      },
    },
  },
});
</script>

Et les compositions correspondantes fonctionnent :

toggleLogic.ts

import {
    
     ref } from "@vue/composition-api";

export const toggleLogic = () => {
    
    
  const show = ref(true);
  const toggle = () => {
    
    
    show.value = !show.value;
  };
  return {
    
     show, toggle };
};

todoListLogic.ts

import {
    
     reactive, computed, ComputedRef } from "@vue/composition-api";

type Todo = {
    
    
  id: number;
  completed: boolean;
  editing: boolean;
  title: string;
};
export const totoListLogic = () => {
    
    
  const state = reactive({
    
    
    todoList: [
      {
    
    
        id: 1,
        title: "hello",
        completed: false,
        editing: false,
      },
      {
    
    
        id: 2,
        title: "world",
        completed: false,
        editing: false,
      },
    ],
    newTodo: undefined as undefined | string,
  });

  const getLatestTodoId: ComputedRef<number> = computed(
    (): number => {
    
    
      const lastTodo: Todo = state.todoList[state.todoList.length - 1];
      return lastTodo.id;
    }
  );

  function addTodo() {
    
    
    if (state.newTodo === undefined) return;
    state.todoList.push({
    
    
      id: getLatestTodoId.value + 1,
      title: state.newTodo,
      completed: false,
      editing: false,
    });
  }

  function editTodo(todo: Todo) {
    
    
    todo.editing = !todo.editing;
  }

  function cancelEdit(todo: Todo) {
    
    
    todo.editing = false;
  }

  function doneEdit(todo: Todo) {
    
    
    const editingTodo: Todo | undefined = state.todoList.find(
      (todo: Todo) => todo.editing === true
    );
    if (editingTodo === undefined) return;
    editingTodo.title = todo.title;
    editingTodo.editing = false;
  }
  return {
    
     state, getLatestTodoId, addTodo, editTodo, cancelEdit, doneEdit };
};

Comparaison des avantages

Les principaux avantages de l'API Composition par rapport à l'API Options sont :

1. 更好的逻辑复用性

- 通过组合函数抽取逻辑,更方便的在组件内外复用
- 更好地代码分割,按功能拆分成更小的逻辑块

2. 更好的代码组织

- 将同一功能的代码收敛在一个函数中,提高内聚性
- 减少组件中的选项混杂,提高可读性

3. 更好的类型推导

- 组合式函数可以利用 Typescript 进行更精确的类型定义
- 提高代码可读性和可维护性

4. 更优雅的处理逻辑抽取

- 将复杂逻辑抽取为可重用的函数,组件只关注业务级代码
- 避免复杂的 mixins 和 HOC 嵌套

5. 更灵活的逻辑复用粒度

- 可以将任意粒度的逻辑封装为组合函数进行复用
- 更灵活的逻辑 boundaries

6. 更直观的响应式编程

- 通过组合式函数内的响应式变量,更直观地表达响应性
- 避免模版和业务逻辑交织在一起

7. 更优雅的增量采用

- 可以与现有的 Options API 共存
- 逐步使用 Composition API 改造旧组件

De manière générale, Composition API présente de grands avantages pour la maintenance et l'expansion d'applications volumineuses et complexes, et peut concevoir une structure de code plus claire et plus flexible.

Comment utiliser @vue/composition-api

Installer

Vue2.7 ou supérieur est livré avec, aucune installation n'est requise ; sous vue2.7, installez-le manuellement npm install @vue/composition-apiet installez le plug-in :

import Vue from 'vue'
import VueCompositionAPI from '@vue/composition-api'

Vue.use(VueCompositionAPI)

Des articles ultérieurs présenteront son principe.

Présentation de l'API

Ce qui suit présente plusieurs API courantes, et les articles suivants présenteront leurs principes un par un :

réf

La fonction ref peut convertir une valeur ordinaire en données réactives. Il renvoie un objet ref mutable et un attribut .value est monté sur l'objet.Nous pouvons lire ou modifier la valeur de ref via cet attribut .value.

Les exemples sont les suivants :

import {
    
     ref } from '@vue/composition-api'

const count = ref(0)

console.log(count.value) // 0

count.value++ 
console.log(count.value) // 1

ref ressemble beaucoup à un conteneur, qui "enferme" des types de données de base tels que Number, String, etc., ce qui en fait une source de données réactive.

réactif

réactive est utilisée pour convertir un objet en données réactives. Il renvoie un objet proxy, et tous les accès aux propriétés et les modifications apportées à l'objet d'origine seront convertis en objets réactifs.

Les exemples sont les suivants :

import {
    
     reactive } from '@vue/composition-api'

const obj = reactive({
    
     count: 0 })

obj.count++ // 响应式更新

réactif est plus adapté aux scénarios où tous les états d'un composant sont définis dans un seul objet, et il peut convertir l'ensemble de l'état de l'objet en un état réactif à la fois.

calculé

La fonction computed est utilisée pour créer une propriété calculée qui est mise en cache et exécutée paresseusement en fonction des dépendances.

Les exemples sont les suivants :

import {
    
     computed } from '@vue/composition-api'

const count = ref(1)

const doubled = computed(() => count.value * 2)

console.log(doubled.value) // 懒执行得到 2

count.value++ // 修改依赖

console.log(doubled.value) // 缓存得到 4

computed évite l'exécution répétée des fonctions et suit automatiquement les dépendances.

montre

La fonction de surveillance est utilisée pour écouter une source de données spécifique et effectuer des effets secondaires dans la fonction de rappel.

Les exemples sont les suivants :

import {
    
     ref, watch } from '@vue/composition-api'

const count = ref(0)

watch(count, (newCount, oldCount) => {
    
    
  console.log(`count变化:${
      
      oldCount} -> ${
      
      newCount}`) 
})

count.value++ // 触发watcher

Il agit comme un auditeur qui voit les changements de comptage et réagit.

toRefs

toRefs peut convertir les propriétés d'un objet réactif en forme de référence.

Les exemples sont les suivants :

import {
    
     reactive, toRefs } from '@vue/composition-api'

const state = reactive({
    
    
  count: 0
})

const {
    
     count } = toRefs(state)

console.log(count.value) // 0

count.value++ // 修改 ref 形式的值

Cela permet de déstructurer facilement un objet réactif tout en conservant le caractère réactif. Il convient de noter que l'objet réactif n'est pas disponible pour le modèle par défaut et ne peut être converti qu'en ref.

installation

setup est le point d'entrée de l'API combinée, où toutes les fonctions combinées sont exécutées.

Les exemples sont les suivants :

import {
    
     ref, reactive } from '@vue/composition-api'

export default {
    
    
  setup() {
    
    
    const count = ref(0)
    const obj = reactive({
    
     foo: 'bar' })
    
    // ... 进行逻辑处理

    return {
    
    
      count,
      obj
    }
  }  
}

cycle de vie

L'API combinée fournit une série de fonctions de crochet correspondant au cycle de vie du composant, qui sont utilisées pour enregistrer les crochets de cycle de vie.

Les exemples sont les suivants :

import {
    
     onMounted } from '@vue/composition-api'

export default {
    
    
  setup() {
    
    
    onMounted(() => {
    
    
      console.log('组件挂载了!')
    })
  }
}

Il existe les fonctions de crochet suivantes :

onBeforeMount - created()
onMounted - mounted()
onBeforeUpdate - beforeUpdate()
onUpdated - updated()
onBeforeUnmount - beforeDestroy()
onUnmounted - destroyed()

Je suppose que tu aimes

Origine blog.csdn.net/mevicky/article/details/132040382
conseillé
Classement