const formRef = ref<InstanceType<typeof ElTable>>();报错

博客提及Vue报错内容及对应的解决办法,虽未给出具体信息,但核心围绕Vue报错问题的处理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上报错内容:

TS2344: Type '{ version: string; install: (app: App<any>, options?: Partial<ConfigProviderProps> | undefined) => vo
id; }' does not satisfy the constraint 'abstract new (...args: any) => any'.
  Type '{ version: string; install: (app: App<any>, options?: Partial<ConfigProviderProps> | undefined) => void; }'
 provides no match for the signature 'new (...args: any): any'.

问题解决:

import ElTable,   {ElMessageBox, FormInstance} from "element-plus";

改成

import  {ElTable, ElMessageBox, FormInstance} from "element-plus";
<template> <div class="container"> <!-- <el-table ref="tableRef" :data="tableData" stripe style="width: 100%" class="non-selectable" @row-dblclick="handleRowDblClick"> --> <div class="container"> <el-table ref="tableRef" :data="tableData" stripe style="width: 100%"> <el-table-column label="排序" width="80"> <template #default="scope"> <el-icon class="drag-handle"><Sort /></el-icon> </template> </el-table-column> <el-table-column prop="id" label="ID" width="120" /> <el-table-column prop="name" label="名称" /> <el-table-column prop="age" label="排序" width="100" /> <el-table-column prop="address" label="地址" /> </el-table> </div> </div> </template> <script setup lang="ts"> import { ref, onMounted, onUnmounted, reactive } from 'vue'; import Sortable from 'sortablejs'; import li from 'linq'; // 定义数据类型 interface TableDataItem { id: number; name: string; age: number; address: string; } const tableRef = ref<InstanceType<(typeof import('element-plus/es'))['ElTable']>>(); const tableData = ref<TableDataItem[]>([ { id: 1, name: '张三', age: 1, address: '北京市朝阳区' }, { id: 2, name: '李四', age: 2, address: '上海市浦东新区' }, { id: 3, name: '王五', age: 3, address: '广州市天河区' }, { id: 4, name: '赵六', age: 4, address: '深圳市南山区' }, { id: 5, name: '钱七', age: 5, address: '杭州市西湖区' } ]); const SourceData = [ { id: 1, name: '张三', age: 1, address: '北京市朝阳区' }, { id: 2, name: '李四', age: 2, address: '上海市浦东新区' }, { id: 3, name: '王五', age: 3, address: '广州市天河区' }, { id: 4, name: '赵六', age: 4, address: '深圳市南山区' }, { id: 5, name: '钱七', age: 5, address: '杭州市西湖区' } ]; onMounted(() => { if (!tableRef.value) return; // 获取表格tbody元素 const tbody = tableRef.value.$el.querySelector('tbody') as HTMLElement; // 初始化Sortable const sortableInstance = new Sortable(tbody, { // handle: '.drag-handle', animation: 150, ghostClass: 'bg-gray-200', onEnd: (evt: Sortable.SortableEvent) => { // 获取拖拽的元素和目标位置的元素 const draggedItem = SourceData[evt.oldIndex]; const targetItem = SourceData[evt.newIndex]; // 交换两个元素的orderId [draggedItem.age, targetItem.age] = [targetItem.age, draggedItem.age]; setTimeout(() => { tableData.value = li .from(SourceData) .orderBy((a) => a.age) .toArray(); console.log('tableData.value', tableData.value); }, 500); } }); }); onUnmounted(() => { // 销毁Sortable实例 // if (state.sortableInstance) { // state.sortableInstance.destroy(); // state.sortableInstance = null; // } }); </script> <style scoped lang="scss"> .container { padding: 20px; max-width: 1000px; margin: 0 auto; } .drag-handle { cursor: grab; color: #909399; padding: 8px; display: inline-block; } .drag-handle:active { cursor: grabbing; } .bg-gray-200 { background-color: #e5e7eb; } </style> 帮我修改此代码 实现拖拽完成后 按照新的age排序 并显示在页面表格内
07-01
<template> <!-- 主弹窗 --> <el-dialog v-model="visible" title="数据选择器" width="75%" top="5vh" align-center destroy-on-close > <div class="conn-container"> <!-- 左侧树形结构 --> <div class="tree-panel"> <el-input v-model="treeFilterText" placeholder="输入机构名称" clearable prefix-icon="Search" /> <el-tree ref="treeRef" :data="treeData" :props="treeProps" :filter-node-method="filterNode" node-key="value" highlight-current @node-click="handleNodeClick" /> </div> <!-- 右侧表格区域 --> <div class="table-panel"> <!-- 数据表格 --> <el-table ref="mainTableRef" :data="tableData" style="width: 100%" height="calc(60vh - 110px)" v-loading="loading" @selection-change="handleSelectionChange" > <el-table-column type="selection" width="55" /> <el-table-column prop="name" label="名称" min-width="180" /> <el-table-column prop="type" label="类型" width="120" /> <el-table-column prop="date" label="日期" width="150" /> <el-table-column prop="status" label="状态" width="100"> <template #default="{ row }"> <el-tag :type="row.status === 'active' ? 'success' : 'info'"> {{ row.status === "active" ? "启用" : "停用" }} </el-tag> </template> </el-table-column> </el-table> <!-- 表格操作栏 --> <div class="table-toolbar"> <el-button type="primary" @click="showSelectedTable" :disabled="selectedData.length === 0" > <el-icon><View /></el-icon> 已选择({{ selectedData.length }}) </el-button> <!-- <div class="selection-controls"> <el-checkbox v-model="selectAllCurrentPage" @change="toggleSelectCurrentPage"> 全选当前页 </el-checkbox> <el-checkbox v-model="selectAllPages" @change="toggleSelectAllPages"> 全选所有页({{ pagination.total }}) </el-checkbox> </div> --> <el-pagination v-model:current-page="pagination.currentPage" v-model:page-size="pagination.pageSize" :page-sizes="[5, 10, 20, 50]" layout="sizes, prev, pager, next, jumper" :total="pagination.total" background @size-change="fetchTableData" @current-change="fetchTableData" /> </div> <!-- 底部功能区 --> <div class="dialog-footer"> <el-button @click="visible = false">取消</el-button> <el-button type="primary" @click="confirmSelection">确认</el-button> </div> </div> </div> </el-dialog> <!-- 已选数据弹窗 --> <el-dialog v-model="selectedDialogVisible" title="已选择数据" width="70%" append-to-body destroy-on-close > <div class="batch-operations"> <el-button type="danger" :disabled="selectedRows.length === 0" @click="batchRemoveSelected"> <el-icon><Delete /></el-icon> 批量删除 </el-button> <span class="selected-count">已选择 {{ selectedData.length }} 项数据</span> </div> <el-table :data="selectedData" border @selection-change="handleSelectedTableSelection"> <el-table-column type="selection" width="55" /> <el-table-column prop="name" label="名称" min-width="180" /> <el-table-column prop="type" label="类型" width="120" /> <el-table-column prop="date" label="日期" width="150" /> <el-table-column label="操作" width="100" fixed="right"> <template #default="{ $index }"> <el-button type="danger" icon="Delete" circle @click="removeSelectedItem($index)" /> </template> </el-table-column> </el-table> <template #footer> <el-button @click="selectedDialogVisible = false">关闭</el-button> </template> </el-dialog> </template> <script lang="ts" setup> import { ref, reactive, watch, onMounted, nextTick } from "vue"; import { ElMessage, ElTree, ElTable, FilterNodeMethodFunction } from "element-plus"; import type { Node } from "element-plus/es/components/tree/src/tree.type"; import { View, Delete } from "@element-plus/icons-vue"; // 类型定义 interface TreeNode { value: number | string; label: string; children?: TreeNode[]; } interface TableData { id: number | string; name: string; type: string; date: string; status: "active" | "inactive"; } interface Pagination { currentPage: number; pageSize: number; total: number; } // 弹窗显示控制 const visible = ref(false); const selectedDialogVisible = ref(false); // 树形结构数据 const treeFilterText = ref(""); const treeRef = ref<InstanceType<typeof ElTree>>(); const treeData = ref<TreeNode[]>([ { value: 1, label: "一级节点", children: [ { value: 11, label: "二级节点1" }, { value: 12, label: "二级节点2" }, { value: 13, label: "二级节点3", children: [ { value: 131, label: "三级节点1" }, { value: 132, label: "三级节点2" }, ], }, ], }, { value: 2, label: "另一个一级节点", children: [ { value: 21, label: "二级节点A" }, { value: 22, label: "二级节点B" }, ], }, ]); const treeProps = { children: "children", label: "value", }; // 表格数据 const tableData = ref<TableData[]>([]); const loading = ref(false); const mainTableRef = ref(); // 分页配置 const pagination = reactive<Pagination>({ currentPage: 1, pageSize: 10, total: 0, }); // 所有选中ID集合,全局存储选中项的ID(使用Set避免重复) const allSelectedIds = ref<Set<string | number>>(new Set()); const selectedData = ref<TableData[]>([]); // 所有选中数据 const currentPageSelected = ref<TableData[]>([]); // 当前页选中数据 const selectedRows = ref<TableData[]>([]); // 在已选表格中选择的行 const selectAllCurrentPage = ref(false); // 全选当前页 const selectAllPages = ref(false); // 全选所有页 // 树节点搜索 // 树节点过滤 watch(treeFilterText, (val) => { treeRef.value?.filter(val); }); /** * 筛选 */ function filterNode(value: string, data: any) { if (!value) { return true; } return data.label.indexOf(value) !== -1; } // 获取表格数据 const fetchTableData = async () => { try { loading.value = true; // 模拟API请求 await new Promise((resolve) => setTimeout(resolve, 500)); // 生成模拟数据 const mockData: TableData[] = []; const types = ["类型A", "类型B", "类型C", "类型D"]; const statuses: ("active" | "inactive")[] = ["active", "inactive"]; for (let i = 0; i < pagination.pageSize; i++) { mockData.push({ id: i + (pagination.currentPage - 1) * pagination.pageSize, name: `项目 ${i + 1 + (pagination.currentPage - 1) * pagination.pageSize}`, type: types[Math.floor(Math.random() * types.length)], date: ` 2023-${Math.floor(Math.random() * 12) + 1}-${Math.floor(Math.random() * 28) + 1}`, status: statuses[Math.floor(Math.random() * statuses.length)], }); } tableData.value = mockData; pagination.total = 85; // 模拟总条数 // 更新选择状态 updateMainTableSelection(); } catch (error) { ElMessage.error("数据加载失败"); } finally { loading.value = false; } }; // 表格选择变化 const handleSelectionChange = (selection: TableData[]) => { console.log("handleSelectionChange"); // 获取当前页所有ID const currentIds = tableData.value.map((row) => row.id); // 从全局集合中移除当前页所有ID currentIds.forEach((id) => { if (!allSelectedIds.value.has(id)) { allSelectedIds.value.delete(id); // 从全局集合中移除 } }); // 从全局集合中移除当前页数据 selectedData.value = selectedData.value.filter((item) => !currentIds.includes(item.id)); // 将当前页新选中的加入全局集合 currentPageSelected.value = selection; // 更新全局选中ID集合 selection.forEach((item) => allSelectedIds.value.add(item.id)); // 更新选中数据 selectedData.value = Array.from(allSelectedIds.value) .map((id) => [...currentPageSelected.value, ...selectedData.value].find((item) => item.id === id) ) .filter(Boolean) as TableData[]; // 更新全选状态 selectAllCurrentPage.value = selection.length === tableData.value.length; selectAllPages.value = allSelectedIds.value.size === pagination.total; }; // 同步表格选中状态 const syncSelection = () => { nextTick(() => { if (!mainTableRef.value) return; mainTableRef.value.clearSelection(); tableData.value.forEach((row) => { if (allSelectedIds.value.has(row.id)) { mainTableRef.value.toggleRowSelection(row, true); } }); }); }; // 已选表格中的选择变化 const handleSelectedTableSelection = (selection: TableData[]) => { selectedRows.value = selection; }; // 显示已选数据弹窗 const showSelectedTable = () => { selectedDialogVisible.value = true; }; // 删除单个已选项 const removeSelectedItem = (index: number) => { const removedItem = selectedData.value.splice(index, 1)[0]; // 从全局ID集合中移除 allSelectedIds.value.delete(removedItem.id); // 更新主表格选中状态 updateMainTableSelection(); // 如果删除的是当前页的数据,取消其在表格中的选中状态 if (tableData.value.some((item) => item.id === removedItem.id)) { nextTick(() => { const row = tableData.value.find((item) => item.id === removedItem.id); if (row && mainTableRef.value) { mainTableRef.value.toggleRowSelection(row, false); } }); } ElMessage.success("已移除选择项"); }; // 批量删除已选项 const batchRemoveSelected = () => { if (selectedRows.value.length === 0) return; // 从全局ID集合中移除选中的行 const idsToRemove = new Set(selectedRows.value.map((item) => item.id)); idsToRemove.forEach((id) => allSelectedIds.value.delete(id)); // 更新选中数据 selectedData.value = selectedData.value.filter((item) => !idsToRemove.has(item.id)); ElMessage.success(`已移除 ${selectedRows.value.length} 个选项`); selectedRows.value = []; // 更新主表格选中状态 updateMainTableSelection(); }; // 更新主表格选中状态 const updateMainTableSelection = () => { if (!mainTableRef.value) return; // 先清除所有选中状态 mainTableRef.value.clearSelection(); // 重新选中当前页中已选择的数据 nextTick(() => { // 重新设置当前页的选中状态 const selectedIds = allSelectedIds.value; tableData.value.forEach((row) => { if (selectedIds.has(row.id)) { // 使用 setTimeout 0 确保每次操作都在下一个事件循环中执行 setTimeout(() => { mainTableRef.value.toggleRowSelection(row, true); }, 0); } }); }); // 更新全选状态 selectAllCurrentPage.value = currentPageSelected.value.length === tableData.value.length; selectAllPages.value = allSelectedIds.value.size === pagination.total; }; // 全选/取消全选当前页 const toggleSelectCurrentPage = () => { if (selectAllCurrentPage.value) { // 全选当前页 tableData.value.forEach((row) => { allSelectedIds.value.add(row.id); }); } else { // 取消全选当前页 tableData.value.forEach((row) => { allSelectedIds.value.delete(row.id); }); } // 更新选中数据 selectedData.value = Array.from(allSelectedIds.value) .map( (id) => tableData.value.find((item) => item.id === id) || selectedData.value.find((item) => item.id === id) ) .filter(Boolean) as TableData[]; // 更新表格选中状态 updateMainTableSelection(); }; // 全选/取消全选所有页 const toggleSelectAllPages = () => { if (selectAllPages.value) { // 全选所有页 allSelectedIds.value = new Set(Array.from({ length: pagination.total }, (_, i) => i)); // 实际项目中需要从所有页获取数据 selectedData.value = [...tableData.value]; // 简化示例 } else { // 取消全选所有页 allSelectedIds.value.clear(); selectedData.value = []; } // 更新表格选中状态 updateMainTableSelection(); }; // 确认选择 const confirmSelection = () => { if (selectedData.value.length === 0) { ElMessage.warning("请至少选择一条数据"); return; } emit("confirm", selectedData.value); visible.value = false; }; // 树节点点击事件 const handleNodeClick = (node: Node) => { fetchTableData(); }; // 暴露打开方法 const open = () => { visible.value = true; // 重置选择状态 allSelectedIds.value.clear(); selectedData.value = []; selectAllCurrentPage.value = false; selectAllPages.value = false; fetchTableData(); }; // 监听已选择数据变化,更新表格选中状态 watch( selectedData, () => { selectAllPages.value = allSelectedIds.value.size === pagination.total; }, { deep: true } ); // 初始化树形结构 onMounted(() => { // 展开第一层节点 setTimeout(() => { treeData.value.forEach((node) => { treeRef.value?.store.nodesMap[node.value]?.expand(); }); }, 100); }); // 定义事件 const emit = defineEmits<{ (e: "confirm", data: TableData[]): void; }>(); defineExpose({ open }); </script> <style scoped lang="scss"> .conn-container { display: flex; height: 100%; gap: 16px; } :deep(.el-dialog) { padding: 1px; .el-dialog__header { padding: 10px; } .el-dialog__body { padding: 10px; } } .tree-panel { width: 30%; height: 100%; display: flex; flex-direction: column; padding: 16px; } .table-panel { width: 70%; display: flex; flex-direction: column; gap: 5px; } .table-toolbar { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; padding: 5px 0; .el-button { margin-right: auto; } } .dialog-footer { display: flex; justify-content: flex-end; margin-top: 20px; padding-top: 15px; border-top: 1px solid var(--el-border-color-light); gap: 12px; } .batch-operations { display: flex; justify-content: space-between; align-items: center; margin-bottom: 15px; .selected-count { color: var(--el-text-color-secondary); font-size: 14px; } } /* 响应式调整 */ @media (max-width: 1200px) { .dialog-body { flex-direction: column; height: auto; } .tree-panel, .table-panel { width: 100%; padding: 0; } .tree-panel { border-right: none; border-bottom: 1px solid var(--el-border-color-light); padding-bottom: 20px; margin-bottom: 20px; height: 40vh; } .table-toolbar { flex-direction: column; align-items: flex-start; .selection-controls { width: 100%; justify-content: space-between; margin: 10px 0; } } } /* 美化滚动条 */ .tree-container::-webkit-scrollbar { width: 6px; height: 6px; } .tree-container::-webkit-scrollbar-thumb { background-color: var(--el-color-primary-light-5); border-radius: 3px; } .tree-container::-webkit-scrollbar-track { background: var(--el-fill-color-lighter); } </style> 优化样式,树的宽度为当前页面的100
最新发布
07-20
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值