当前位置: 首页 > 知识库问答 >
问题:

vue.js - vue3 代码拆分最佳实践?

曾歌者
2023-08-20

老项目遗留了一些代码,VUE页面里面的代码太长了
想把TS代码拆分出来,请问最佳实践是什么样子的?
旧代码:

<template>    <div class="table-tree-container">        <div class="list-tree-wrapper">            <div class="list-tree-operator">                <t-input v-model="filterText" placeholder="请输入过滤关键词" @change="onTreeInput">                    <template #suffix-icon>                        <search-icon size="var(--td-comp-size-xxxs)" />                    </template>                </t-input>                <t-button block @click="onCleanActive" variant="dashed" size="small" class="mt-2">                    <template #icon>                        <i class="ri-close-circle-line mr-1"></i>                    </template>                    清空选中项                </t-button>                <t-tree class="mt-2" :data="categoryTree" activable v-model:actived="treeActived" @active="onTreeActive" :filter="filterByText" expand-all :keys="{ value: 'id', label: 'cate_name' }" hover expand-on-click-node />            </div>            <div class="list-tree-content">                <div class="index-container">                    <t-card :bordered="false" :title="cardTitle" class="list-card-container">                        <template #actions>                            <t-button @click="onAdd" v-permission="'article/add'">                                <template #icon>                                    <i class="ri-add-line mr-1"></i>                                </template>                                添加                            </t-button>                        </template>                        <t-space>                            <t-select :options="REC_OPTIONS" v-model="searchForm.rec" clearable placeholder="请选择推荐位" />                            <t-select :options="STATUS_OPTIONS" v-model="searchForm.status" clearable placeholder="请选择状态" />                            <t-input v-model="searchForm.kw" placeholder="请输入你需要搜索的内容" clearable />                            <t-button @click="onSearch" theme="default">                                <template #icon>                                    <i class="ri-search-line mr-1"></i>                                </template>                                搜索                            </t-button>                            <t-dropdown :options="DROPDOWN_OPTIONS" :max-column-width="200">                                <t-button variant="outline" theme="success"> 选中项 <i class="ri-arrow-down-s-line ml-1 icon-valign-top"></i> </t-button>                            </t-dropdown>                        </t-space>                        <t-row :gutter="16" class="table-container">                            <t-col>                                <t-table :data="data" stripe :columns="TABLE_COLUMNS" :vertical-align="'top'" :hover="true" :pagination="pagination" @select-change="onSelectChange" @page-change="onPageChange" :loading="dataLoading" :row-key="'id'">                                    <template #id="{ row }">                                        <var>{{ row['id'] }}</var>                                    </template>                                    <template #status="{ row }">                                        <t-tag v-if="Number(row['status']) === 1" theme="success" variant="light"> 公开</t-tag>                                        <t-tag v-else-if="Number(row['status']) === 0" theme="danger" variant="light"> 锁定</t-tag>                                        <t-tag v-else theme="primary" variant="light"> 定时发布</t-tag>                                    </template>                                    <template #sort_by="{ row }">                                        <t-input-number v-permission="'article/sort'" v-model="row.sort_by" @change="(v) => onSortChange(row, v)" theme="column"></t-input-number>                                    </template>                                    <template #created_at="{ row }">                                        {{ formatTime(row['created_at']) }}                                    </template>                                    <template #cid="{ row }">                                        {{ formatCate(row['cid']) }}                                    </template>                                    <template #author="{ row }">                                        {{ row['author'] }}                                    </template>                                    <template #op="{ row }">                                        <a class="t-button-link" v-permission="'article/edit'" @click="onEdit(row)">编辑</a>                                    </template>                                </t-table>                            </t-col>                        </t-row>                    </t-card>                </div>            </div>        </div>    </div></template><script setup lang="ts">import { ref, onMounted, reactive } from 'vue';import { MessagePlugin, DialogPlugin } from 'tdesign-vue-next';import { STATUS_OPTIONS, REC_OPTIONS } from '@/config/global';import helper from '@/utils/helper';import { getArticleList, updateArticleSort, updateArticleStatus, deleteArticle } from '@/api/article';import { IApiResponse } from '@/types';import { TABLE_COLUMNS } from '@/pages/article/constants';import { useRouter } from 'vue-router';import { getArticleStore } from '@/store';const router = useRouter();const cardTitle = ref(helper.getPageTitle());const cateId = ref(0);const categoryTree = ref([]);const articleStore = getArticleStore();const fetchCategoryTree = async () => {    const { treeList } = articleStore;    if (helper.len(treeList) === 0) {        try {            await articleStore.getTreeCategory();            categoryTree.value = articleStore.treeList;        } catch (e) {            return Promise.reject(e);        }    } else {        categoryTree.value = treeList;    }};const formatCate = (v) => {    if (helper.len(categoryTree.value) <= 0) {        return '';    }    let item = categoryTree.value.find((ele) => {        if (Number(ele.id) === Number(v)) {            return ele;        }        return null;    });    if (!item) {        return v;    }    return item.cate_name;};const formatTime = (v) => {    if (!v) {        return '';    }    return helper.time().dateTimeDisplay(v);};const onAdd = () => {    let url = '/article/add';    if (cateId.value) {        url += '?cate_id=' + cateId.value;    }    router.push(url);};const onEdit = (row) => {    router.push('/article/edit?id=' + row.id);};const onSearch = () => {    fetchData(searchForm.value);};const data = ref([]);const dataLoading = ref(false);const pagination = reactive({    current: 1,    pageSize: Number(import.meta.env.VITE_APP_PAGE_SIZE),    total: 0,    showJumper: true,});const searchForm = ref({    kw: '',    cid: null,    rec: null,    status: null,    page: pagination.current,    page_size: pagination.pageSize,});const onSortChange = async (row, value) => {    try {        helper.fullLoading();        console.log(value, row);        const resp: IApiResponse = await updateArticleSort({ id: row.id, value: value });        if (resp.code === 0) {            MessagePlugin.success('操作成功');            await fetchData();        } else {            return Promise.reject(new Error(resp.message));        }    } catch (e) {        MessagePlugin.error(e.message);    } finally {        helper.hideLoading();    }};const onPageChange = async (pageInfo) => {    const { current, pageSize } = pageInfo;    pagination.current = current;    pagination.pageSize = pageSize;    await fetchData({ page: current, page_size: pageSize });};const onSelectChange = (value) => {    selection.value = value;};const fetchData = async (params = null) => {    dataLoading.value = true;    try {        let def = { ...searchForm.value };        if (params) {            def = Object.assign(def, params);        }        const res: IApiResponse = await getArticleList(def);        if (res.code === 0) {            const { data_list = [] } = res.data;            data.value = data_list;            pagination.total = res.data.total_count;        } else {            return Promise.reject(new Error(res.message));        }    } catch (e) {        data.value = [];        console.log(e);        //MessagePlugin.error(e.message);        pagination.total = 0;    } finally {        dataLoading.value = false;    }};const onTreeActive = async (v, c) => {    searchForm.value.cid = c.node.data.id;    router.push({        query: {            cate_id: searchForm.value.cid,        },    });    await fetchData();};const onCleanActive = async () => {    router.push({        query: {},    });    searchForm.value.cid = null;    treeActived.value = [];    await fetchData();};const treeActived = ref([]);const filterByText = ref();const filterText = ref();const onTreeInput = () => {    filterByText.value = (node) => {        const rs = node.label.indexOf(filterText.value) >= 0;        return rs;    };};onMounted(async () => {    cateId.value = helper.getQueryToNumber('cate_id', router);    if (cateId.value) {        searchForm.value.cid = cateId.value;    }    await fetchCategoryTree();    await fetchData();});const selection = ref([]);const DROPDOWN_OPTIONS = [    {        content: '删除选中内容',        value: 2,        onClick: () => {            dropdownClick({ value: 2 });        },    },    {        content: '修改为公开',        value: 1,        onClick: () => {            dropdownClick({ value: 1 });        },    },    {        content: '修改为隐藏',        value: 0,        onClick: () => {            dropdownClick({ value: 0 });        },    },];const onStatus = async (params) => {    try {        helper.fullLoading();        const resp: IApiResponse = await updateArticleStatus(params);        if (resp.code === 0) {            MessagePlugin.success('操作成功');            await fetchData();        } else {            return Promise.reject(new Error(resp.message));        }    } catch (e) {        MessagePlugin.error(e.message);    } finally {        helper.hideLoading();    }};const onDelete = async (params) => {    const dialogNode = DialogPlugin.confirm({        header: '系统提示',        body: '确定要删除吗?',        theme: 'info',        onConfirm: async () => {            dialogNode.hide();            await deleteAction(params);        },    });};const deleteAction = async (params) => {    try {        helper.fullLoading();        const resp: IApiResponse = await deleteArticle(params);        if (resp.code === 0) {            MessagePlugin.success('操作成功');            await fetchData();        } else {            return Promise.reject(new Error(resp.message));        }    } catch (e) {        MessagePlugin.error(e.message);    } finally {        helper.hideLoading();    }};const dropdownClick = (data) => {    if (data.value === 1 && helper.len(selection.value) === 0) {        MessagePlugin.warning('请选择要操作的数据');        return false;    }    let params = { ids: selection.value.join(',') };    if (data.value === 2) {        onDelete(params);    } else {        params['status'] = data.value;        onStatus(params);    }};</script><style lang="less" scoped>.table-tree-container {    background-color: var(--td-bg-color-container);    border-radius: var(--td-radius-medium);    .t-tree {        margin-top: var(--td-comp-margin-xxl);    }}.list-tree-wrapper {    overflow-y: hidden;    background: #fff;}.list-tree-operator {    width: 210px;    float: left;    padding: var(--td-comp-paddingTB-xxl) var(--td-comp-paddingLR-xxl);}.list-tree-content {    border-left: 1px solid var(--td-border-level-1-color);    overflow: auto;}</style>

共有1个答案

汪成仁
2023-08-20

没仔细看你的代码,说说我的重构经验:

  1. 上下文不相关的函数,抽出来放到工具函数里。包括网络请求,都可以抽出来。
  2. 能够复用的功能,抽出来做成组件。组件的颗粒度以 方便理解 为准,细一点没关系。
  3. 样式我已经完全拥抱 TailwindCSS 了,所以几乎不存在 <style>
 类似资料:
  • 我有一个关于用wsimport工具生成Java工件的问题(by Maven Jax-WS) 当我从WSDL生成Java工件时,我希望将web服务项目打包为WAR文件,将其客户机打包为JAR文件。 在哪里放置生成的工件,在哪里放置WSDL?关于组织Web服务项目的最佳实践是什么? 提前谢谢你! 向你问好,尤里卡·克里扎尼克

  • 下面是WebPack4配置代码: 新的配置代码从项目中使用的节点模块中获取所有代码。但我只希望拆分供应商库(我在enrtry配置部分定义),而不希望拆分node_modules中的所有代码。 在本例中:“babel-polyfill”,“react”,“react-dom”,“jquery”,“bootstrap”

  • 我希望一些帮助处理一个奇怪的边缘案例与我正在构建的一个分页API。 与许多API一样,这个API分页了大量的结果。如果查询/foos,将得到100个结果(即foo#1-100),以及一个指向/foos?page=2的链接,该链接将返回foo#101-200。 不幸的是,如果在API使用者进行下一个查询之前从数据集中删除了foo#10,/foos?page=2将抵消100并返回foos#102-20

  • 问题内容: 我有一种情况,我必须在共享主机提供商上更新网站。该站点具有CMS。使用FTP上传CMS的文件非常简单。 我还必须导入一个大的数据库文件(相对于PHP脚本而言)(大约2-3 MB未压缩)。Mysql已关闭,无法从外部访问,因此我必须使用FTP上传文件,然后启动PHP脚本将其导入。可悲的是,我无权访问命令行功能,因此必须使用本地PHP进行解析和查询。我也不能使用LOAD DATA INFI

  • 本文向大家介绍vue.js todolist实现代码,包括了vue.js todolist实现代码的使用技巧和注意事项,需要的朋友参考一下 案例知识点: 1.vue.js基础知识 2.HTML5 本地存储localstorage store.js代码 App.vue代码 总结 以上所述是小编给大家介绍的vue.js todolist实现代码,希望对的大家有所帮助!

  • 问题内容: 与该Wiki相反,我正在从编码的角度寻找实现Swing GUI控件的正确方法。 我一直在寻求学习Java及其GUI工具的方法,但是我发现Internet教程之后的Internet教程将所有内容都扔了进去,我知道这是不对的。 我也尝试过Netbeans等RAD系统和其他“可视”编辑器,但是到编码时,我已经有了一大堆代码,但我不知道它做什么的一半,所以我打算学习手动进行代码摆动,我知道基本