前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Vue3 Composition API教程及示例

Vue3 Composition API教程及示例

作者头像
前端知否
发布2020-03-23 18:03:54
4.7K0
发布2020-03-23 18:03:54
举报
文章被收录于专栏:前端知否前端知否

Vue引入了Composition API(基于功能的API)作为当前基于Option的API的补充。该API将随Vue 3一起发布,但是现在您可以通过将Vue 3 Composition API添加到您的Vue 2应用程序中来进行尝试。

在本教程中,我将向您展示:

  • 新的Vue Composition API概述以及与基于经典Vue Options的API的比较
  • 使用新API实现Vue组件的示例:Props,data,watch,生命周期钩子
  • 充分利用新的Vue 3 Composition API(基于函数的API)的示例:将代码拆分为函数

添加Vue Composition API会发生什么变化?

一切仍将像以前一样工作。几乎没有任何变化:

  • 命令行界面
  • 模板语法
  • 对象格式
  • 数据响应
  • 计算属性,观察者和组件生命周期的概念
  • SFC格式
  • Vue框架的渐进性
基于选项的API与组合API

当前基于选项的API概念与新的合成API(基于函数的API)概念的区别在于:

  • 基于选项的API:组件包含属性/方法/选项的类型。
  • 组合API:组件将逻辑封装到函数中。

组件选项可能变得组织起来复杂且难以维护(怪异的组件)。逻辑可能涉及props和data()的属性,某些方法,某个钩子(beforeMount/mounted)以及值班的watch。因此,一个逻辑将分散在多个选项中。

使用Composition API,每个功能都是大型组件的一部分,它封装了与逻辑相关的所有代码(属性,方法,钩子,watch观察者)。现在,较小的代码(函数)可以重复使用,并且组织得很好。

在当前的Vue 2项目中使用Vue 3 Composition API

通过安装@vue/composition-api模块,我们可以在当前的Vue 2.x项目中使用新的Vue 3 Composition API。

非常简单,只需运行以下命令:

代码语言:javascript
复制
npm install @vue/composition-api

or

yarn add @vue/composition-api
代码语言:javascript
复制

然后将其导入main.js。

代码语言:javascript
复制
import Vue from 'vue';
import CompositionApi from '@vue/composition-api';

Vue.use(CompositionApi);
代码语言:javascript
复制
Vue setup()函数

setup()是新的组件选项,我们将使用新的Vue Composition API设置组件的逻辑。如果setup()函数变得复杂,我们可以轻松地将其拆分为多个具有逻辑主题的函数。

何时调用setup()?

创建组件实例时,在props解析后调用它。

现在,使用setup()函数查看Vue组件:

代码语言:javascript
复制
const MyComponent = {
  props: {
    name: String
  },

  setup(props, context) {
    console.log(props.name);
    // context.attrs
    // context.slots
    // context.emit
    // context.parent
    // context.root
  }
}

该函数有2个参数:

props

context

context具有与this.$attrs,this.$slots,this.$emit,this.$parent,this.$root对应的属性(属性,插槽,emit,parent,root)。

即使在更新后,我们也可以使用解构attrs获取最新值

代码语言:javascript
复制
const MyComponent = {
  setup(props, { attrs }) {
    
    function onClick() {
      attrs.foo // 自动更新为最新的值
    }
  }
}

*注意:this关键字在setup()函数中不可用。

所以this.$emit不能这样使用:

代码语言:javascript
复制
setup() {
  function onClick() {
    this.$emit // 无效
  }
}

Composition API中的this.$refs

为了获得对模板中元素或组件实例的引用,我们使用ref API,以便setup()可以为渲染上下文返回可响应和可变对象。

代码语言:javascript
复制
import { ref } from '@vue/composition-api'

const MyComponent = {
  setup(props) {
    const name = ref('bezkoder.com')
    const appendName = () => {
      name.value = `hello ${props.name}`
    }
    return {
      name,
      appendName
    }
  },

  template: `<div @click="appendName">{{ name }}</div>`
}

ref会自动解包为内部值,因此我们无需在模板中附加.value:。{{name}}就足够了,而不是{{name.value}}。

Vue Composition API计算值

基于Vue2选项的API语法:

代码语言:javascript
复制
export default {
  props: {
    title: String
  },

  computed: {
    vTitle() {
      return '-' + this.title + '-';
    },
    itemsQuantity() {
      return this.items.length;
    }
  },

  data() {
    return {
      items: ['This', 'is'],
    };
  },
}

Vue 3 Composition API语法:

代码语言:javascript
复制
import { ref, computed } from '@vue/composition-api';

export default {
  props: {
    title: String
  },
  setup(props) {
    const vTitle = computed(() => '-' + props.title + '-');

    const items = ref(['This', 'is']);
    const itemsQuantity = computed(() => items.value.length);

    return {
      vTitle,
      items,
      itemsQuantity,
    };
  }
};

使用新的计算API,我们可以使用get和set函数创建可写的ref对象。

代码语言:javascript
复制
const count = ref(1)
const double = computed({
  get: () => count.value * 2,
  set: val => { count.value = val - 1 }
})

double.value = 3          // set: count.value = 3 - 1 = 2
console.log(count.value)  // 2
console.log(double.value) // get: count.value * 2 = 4

Vue Composition API Watch

这就是我们使用基于Vue2选项的API语法的方式:

代码语言:javascript
复制
export default {
  data() {
    return {
      items: ['This', 'is'],
      append: ''
    };
  },

  watch: {
    items: {
      handler: function(value, oldValue) {
        this.append = '';
        value.forEach(item => {
          this.append += item + ' ';
        });
      },
      immediate: true
    }
  },
}

就像watch选项一样,每次状态改变时,我们都可以使用新的Vue watch API来执行副作用逻辑代码。

语法为:watch(源,回调,选项)

  • source:可以是getter函数,值包装器或包含上述两种类型的数组(如果要查看多个源)
  • callback:是类似于Vue2 watcher处理程序的函数,带有2个参数:newVal,oldVal。每个参数都可以是一个数组(用于观察多个源): [newVal1,newVal2,... newValN],[oldVal1,oldVal2,... oldValN]
  • options(可选):用于配置观察者类型,其中包括:lazy,deep,flush。
代码语言:javascript
复制
import { ref, watch } from '@vue/composition-api';

export default {
  setup(props) {
    const items = ref(['This', 'is']);
    const append = ref('');

    watch(
      // getter
      () => items.value,

      // callback
      (items, oldItems) => {
        append.value = '';
        items.forEach(item => {
          append.value += item + ' ';
        });
      },

      // watch Options
      {
        lazy: false // immediate: true
      }
    )

    return {
      items,
      append
    };
  }
};

如果我们想观察多个源:

代码语言:javascript
复制
watch([aRef, bRef], ([a, b], [prevA, prevB]) => {
  /* ... */
})

我们还可以将多个源观察程序拆分为较小的观察程序。这有助于我们组织代码并创建具有不同选项的观察程序:

代码语言:javascript
复制
watch(
  // getter
  () => items.value,

  // callback
  (items, oldItems) => {
    append.value = '';
    items.forEach(item => {
      append.value += item + ' ';
    });
  },

  // watch Options
  {
    lazy: false // immediate: true
  }
)

watch(
  // getter
  () => todo.value.length,

  // callback
  (length, oldLength) => {
    todoLength.value = length;
  },

  // watch Options
  {
    lazy: true // immediate: false
  }
)

Vue Composition API生命周期钩子

使用Vue2,我们通过以下方式实现Lifecycle Hooks函数:

代码语言:javascript
复制
export default {
  beforeMount() {
    console.log('V2 beforeMount!')
  },

  mounted() {
    console.log('V2 mounted!')
  }
};

新的Vue 3 Composition API具有等效的功能,我们可以在setup()函数内使用带前缀的功能:

代码语言:javascript
复制
import { onBeforeMount, onMounted } from '@vue/composition-api';

export default {
  setup() {
    onBeforeMount(() => {
      console.log('V3 beforeMount!');
    })

    onMounted(() => {
      console.log('V3 mounted!');
    })
  }
};
代码语言:javascript
复制

您可以在下表中看到Vue2 生命周期Options与Composition API之间的映射:

将逻辑封装到函数中

现在,我们将以上所有代码组合到一个Vue组件中,您可以看到一个包含多个逻辑的复杂组件。我们需要为标题,待办事项和项目实现对应的逻辑:

代码语言:javascript
复制
import { ref, reactive, computed, watch, onBeforeMount, onMounted } from '@vue/composition-api';

export default {
  props: {
    title: String,
    initInput: String
  },

  setup(props) {
    const vTitle = computed(() => '-' + props.title + '-');

    const todo = ref(props.initInput);
    const todoLength = ref(0);

    const items = ref(['This', 'is']);
    const itemsQuantity = computed(() => items.value.length);
    const append = ref('');

    watch(
      // getter
      () => items.value,

      // callback
      (items, oldItems) => {
        append.value = '';
        items.forEach(item => {
          append.value += item + ' ';
        });
      },

      // watch Options
      {
        lazy: false // immediate: true
      }
    )

    watch(
      // getter
      () => todo.value.length,

      // callback
      (length, oldLength) => {
        todoLength.value = length;
      },

      // watch Options
      {
        lazy: false // immediate: true
      }
    )

    const add = () => {
      if (todo.value) {
        items.value.push(todo.value);
        todo.value = '';
      }
    };

    const remove = index => {
      items.value.splice(index, 1);
    };

    onBeforeMount(() => {
      console.log('V3 beforeMount!');
    })

    onMounted(() => {
      console.log('V3 mounted!');
    })

    return {
      vTitle,
      todo,
      todoLength,
      items,
      itemsQuantity,
      append,
      add,
      remove
    };
  }
};

是时候利用Vue Composition API了:将复杂的组件拆分为多个对应于不同逻辑的函数:

代码语言:javascript
复制
import { ref, computed, watch, onBeforeMount, onMounted } from "@vue/composition-api";

function useTitle(props) {
  const vTitle = computed(() => "-" + props.title + "-");

  return {
    vTitle
  };
}

function useTodoLength(todo) {
  const todoLength = ref(0);

  watch(
    // getter
    () => todo.value.length,

    // callback
    (length, oldLength) => {
      todoLength.value = length;
    },

    // watch Options
    {
      lazy: false // immediate: true
    }
  );

  return {
    todoLength
  };
}

function useItems(todo) {
  const items = ref(["This", "is"]);
  const itemsQuantity = computed(() => items.value.length);
  const append = ref("");

  watch(
    // getter
    () => items.value,

    // callback
    (items, oldItems) => {
      append.value = "";
      items.forEach(item => {
        append.value += item + " ";
      });
    },

    // watch Options
    {
      lazy: false // immediate: true
    }
  );

  const add = () => {
    if (todo.value) {
      items.value.push(todo.value);
      todo.value = "";
    }
  };

  const remove = index => {
    items.value.splice(index, 1);
  };

  return {
    items,
    itemsQuantity,
    append,
    add,
    remove
  };
}

export default {
  props: {
    title: String,
    initInput: String
  },

  setup(props) {
    const todo = ref(props.initInput);

    onBeforeMount(() => {
      console.log("V3 beforeMount!");
    });

    onMounted(() => {
      console.log("V3 mounted!");
    });

    return {
      todo,
      ...useTitle(props),
      ...useTodoLength(todo),
      ...useItems(todo)
    };
  }
};
最后

使用旧的基于Vue选项的API时,您可能会感到熟悉舒适;或者,您不希望将所有内容都作为函数,而是继续保持OOP思维方式的属性/方法。这些想法都没问题。同时开发者们也在积极开发Vue,并使其逐年变得更好,并为我们提供更多选择。何不尝试一下,感觉也很不错哦。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端知否 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 基于选项的API与组合API
  • 在当前的Vue 2项目中使用Vue 3 Composition API
  • Vue setup()函数
  • Composition API中的this.$refs
  • Vue Composition API计算值
  • Vue Composition API Watch
  • Vue Composition API生命周期钩子
  • 将逻辑封装到函数中
  • 最后
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档