背景、Composition和Option对比
#Composition-api使用背景
Composition-api
是vue3的新特性,在vue2中可以安装@vue/composition-api
使用该语法,目前项目现状是用的vue2,所以集成了@vue/Composition-api
插件。但是在项目开发中使用@vue/composition-api
过程中存在了一些问题,例如:Option-api
和Composition-api
在项目中混用或者所有的业务逻辑都写在了setup()函数中,用起来跟Option-api
没有太大的区别,且使得setup()函数很大很臃肿,难以维护。所以编写此文档作为入门学习。
#Option-api 存在的问题
使用传统Options-api
中,新增或者修改一个需求,就需要分别在data,methods,computed里修改 。如果代码量少的情况下,看着还是比较清爽的,但是如果对于中大型项目,或者对于单文件代码量上千行的情况,Option-api
就显得很臃肿,维护困难。
#Mixin和Composition-api
Mixin:在vue2中使用Mixin提取公共方法
优点:
1、组件逻辑复用。
2、可以定义共用的变量,在每个组件中使用,引入组件中之后,各个变量是相互独立的,值的修改在组件中不会相互影响。
缺点:
1、命名冲突问题!
2、可能会被滥用!
3、不可知,不易维护, 写不好代码就容易散、新手难以理解。
Composition-api:使用use提取公共方法
优点:
1、更好的组织代码,函数,让相关功能的代码更加有序的组织在一起。
2、如果可以抽离公共的js逻辑更好,实现代码复用,若不能实现复用,单独抽离业务功能代码也易于维护。
3、现了功能的分离,代码更加有序。
缺点:
1、对于小型项目逻辑不复杂的场景,Composition-api
没有Option-api
易读和看着清爽。
Composition-api和Option-api插图对比
![](/i/l/?n=22&i=blog/1093245/202209/1093245-20220905152555475-2099341385.png)
项目实践
#业务场景
以上场景是发起上报、配合修改菜单的列表页面,对于tab上的设备、软件、服务、系统、网站、网络、单位接口一样,用传参区分。后端列表定义为一个接口,在src下创建hook目录,在hook目录下创建commonUse.js
import { reactive } from '@vue/composition-api'; import { hainaChangedRecordsSearchByConditionUploadRequest } from '@/services/api'; //列表请求 export const useRequest = (activeName, dataType, org_id) => { let formData = reactive({ assetName: '', //资产名称 assetIp: '', //资产Ip processStatusList: '', //流程状态 type: '' //维护操作类别 }); const request = async ({ page, size }) => { const params = { ...formData, assetType: activeName.value, //tab的类型值 设备、软件、服务、系统、网站、网络、单位 dataType, //用于区分发起上报还是配合修改 org_id: org_id.value, //单位id offset: page, limit: size, }; const { data } = await hainaChangedRecordsSearchByConditionUploadRequest(params); return { data: { data: data.items, total: data.total } }; }; return { formData, request, }; };
<template> ... <sti-pro-search-form ref="form" :model="formData" :span="4" @search="reload" @reset="handleReset" > <sti-pro-search-form-item label="资产名称"> <sti-input v-model="formData.assetName" placeholder="请输入资产名称" clearable style="width: 220px;" /> ... ... <sti-table ref="table" width="100%" :fetch-data="request" :table-header="tableHeader" :need-init="false" @selection-change="handleSelectionChange" /> ... </template> <script> import { defineComponent } from '@vue/composition-api'; import { useRequest, useTableHeader, useTabClick, useTabData } from '@/src/hook/commonUse'; export default defineComponent({ name: 'SubjectReportCoordinationModify', setup() { ... //获取tab的数据 const { org_id } = useTabData(); //tab切换的方法 const { activeName } = useTabClick(); //获取表头字段 const { tableHeader } = useTableHeader(activeName); //获取列表请求接口 //重点在这,列表的请求 上述的useTabData、useTabClick、useTableHeader只为获取useRequest参数 const { formData, request } = useRequest(activeName, '1', org_id); ... return { formData, request, tableHeader } } }) </script>
业务场景
在系统的多个页面需要用到下载功能,在src下创建hook目录,在hook目录下创建commonUse.js
import { Message } from '@atsfe/qaxd';
import { hainaFileDownloadFileGetRequest, hainaFileGetFileDetailGetRequest } from '@/services/api';
//下载文件
export const useDownLoad = () => {
const handleDownLoad = async (file_id) => {
if (!file_id) return Message.warning('文件不存在');
const { data } = await hainaFileGetFileDetailGetRequest({ file_id });
const res = await hainaFileDownloadFileGetRequest({
file_id,
}, {responseType: 'blob'});
let url = window.URL.createObjectURL(new Blob([res]));
let link = document.createElement('a');
link.style.display = 'none';
link.href = url;
link.setAttribute('download', data.name);
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
};
return {
handleDownLoad
};
};
<template> ... <div class="margin-t"> <q-button type="primary" @click="handleDownLoad(data.file_id)"> 下载附件 </q-button> </div> ... </template> <script> import { defineComponent } from '@vue/composition-api'; import { useDownLoad } from '@/src/hook/commonUse'; export default defineComponent({ setup() { ... //下载附件 const { handleDownLoad } = useDownLoad(); ... return { handleDownLoad } } }) </script>
总结
以上为Composition-api
的简单使用方法,主要是抽离公共js代码复用及业务代码按功能拆分,把之前在data, computed, methods, mounted 的代码抽离到use方法中单独维护,针对于逻辑代码不是很复杂的页面Composition-api
没有Option-api
看着清爽,但是Composition-api
针对于逻辑比较复杂代码量上千行的业务具有明显的优势。另外Composition-api
不需要考虑this指向,属于函数式编程,更接近原生体验。