营销型网站设计分析案例,松山湖网站建设公司,wordpress调用分类的所有子目录,做一个公众号要多少钱?1. 树形结构显示
显示文件夹和文件#xff1a;使用 el-tree 组件展示树形结构#xff0c;文件夹和文件的图标通过 el-icon 进行动态显示。文件夹使用 Folder 图标#xff0c;文件使用 Files 图标。节点点击#xff1a;点击树形节点后#xff0c;会将选中的节点保存到 sel…
1. 树形结构显示
显示文件夹和文件使用 el-tree 组件展示树形结构文件夹和文件的图标通过 el-icon 进行动态显示。文件夹使用 Folder 图标文件使用 Files 图标。节点点击点击树形节点后会将选中的节点保存到 selectedNode 中方便后续操作如重命名、删除。
2. 创建文件夹
在根目录或者当前选中的文件夹下点击 新建文件夹 按钮触发 createFolder 方法创建一个新的文件夹。新文件夹将被添加到当前选中节点的 children 数组中或者如果没有选中任何节点则将文件夹添加到根目录。
3. 创建文件
类似于文件夹点击 新建文件 按钮触发 createFile 方法创建一个新的文件并将其添加到当前选中的文件夹下或者根目录。
4. 删除文件/文件夹
通过点击 删除文件/文件夹 按钮触发 removeFile 方法删除当前选中的文件或文件夹。删除操作会检查所选文件夹或文件的父级节点如果有父节点直接从父节点的 children 中移除该项如果是根节点则从根目录数组中删除。
5. 重命名文件/文件夹
通过右键点击某个节点弹出自定义的上下文菜单。选择 重命名 选项后触发 renameNode 方法通过 prompt 弹窗输入新的名称并更新节点的 label。
6. 删除文件/文件夹右键菜单
右键点击文件夹或文件弹出自定义右键菜单选择 删除 后会弹出确认对话框确认删除后调用 deleteNode 删除当前选中的文件/文件夹。
7. 上下文菜单
在树形结构中右键点击文件夹或文件时会弹出自定义的上下文菜单显示 重命名 和 删除 选项。上下文菜单会根据鼠标点击的位置动态显示通过 contextMenuPosition 控制菜单的位置。
8. 事件监听
点击外部区域隐藏上下文菜单使用 document.addEventListener(click, handleOutsideClick) 监听点击事件点击树形组件外部区域时隐藏上下文菜单并清空选中的节点。组件卸载时移除事件监听在组件卸载时通过 onBeforeUnmount 钩子移除点击外部区域的事件监听避免内存泄漏。 script setup
import { ref, onMounted, onBeforeUnmount } from vue;
import { Folder, Files } from element-plus/icons-vue;// 在组件挂载后添加事件监听
onMounted(() {document.addEventListener(click, handleOutsideClick);
});
// 在组件卸载前移除事件监听
onBeforeUnmount(() {document.removeEventListener(click, handleOutsideClick);
});
// 定义树形数据
const data ref([{label: 文件夹1,type: folder,children: [{label: 1-1,type: folder,children: [{label: 1-1-1,type: file,},],},],},{label: 文件夹2,type: folder,children: [{label: 2-1,type: folder,children: [{label: 2-1-1,type: file,},],},{label: 2-2,type: file,},],},{label: 文件夹3,type: folder,children: [],},
]);// 配置树形数据的显示属性指定文件夹使用 Folder 图标
const defaultProps {children: children,label: label,icon: icon, // 图标属性
};
// 当前选中的节点
const selectedNode ref(null);
const handleNodeClick (data) {selectedNode.value data;
};
// 监听点击事件判断点击是否在树形组件外
const handleOutsideClick (event) {const treeElement document.querySelector(.el-tree); // 获取树形组件的 DOM 元素const buttonContainer document.querySelector(.header); // 获取按钮区域// 判断点击区域是否在树形组件或按钮区域外if (!treeElement.contains(event.target) !buttonContainer.contains(event.target)) {selectedNode.value null; // 如果点击区域不是树或按钮区域则清除选中的节点showContextMenu.value false; // 隐藏菜单}
};
// 创建文件夹
const createFolder () {const newFolder {label: 新文件夹,type: folder,children: [],};if (selectedNode.value selectedNode.value.type folder) {// 在选中的文件夹下创建selectedNode.value.children.push(newFolder);} else {// 根目录下创建data.value.push(newFolder);}
};// 创建文件
const createFile () {const newFile {label: 新文件,type: file,};if (selectedNode.value selectedNode.value.type folder) {// 在选中的文件夹下创建selectedNode.value.children.push(newFile);} else {// 根目录下创建data.value.push(newFile);}
};// 删除文件或文件夹
const removeFile () {if (!selectedNode.value) {alert(请先选择一个文件或文件夹);return;}const parentNode findParentNode(data.value, selectedNode.value);if (parentNode) {const index parentNode.children.findIndex((item) item.label selectedNode.value.label);if (index ! -1) {parentNode.children.splice(index, 1);selectedNode.value null; // 删除后清空选中的节点}} else {// 如果没有父节点表示是根节点直接从根节点删除const index data.value.findIndex((item) item.label selectedNode.value.label);if (index ! -1) {data.value.splice(index, 1);selectedNode.value null; // 删除后清空选中的节点}}
};
// 查找父节点
const findParentNode (nodes, targetNode) {for (let node of nodes) {if (node.children node.children.includes(targetNode)) {return node;} else if (node.children) {const result findParentNode(node.children, targetNode);if (result) return result;}}return null;
};
// 控制上下文菜单显示
const showContextMenu ref(false);
// 上下文菜单位置
const contextMenuPosition ref({ top: 0, left: 0 });
//右键显示菜单
const handleContextMenu (event, data, node) {event.preventDefault(); // 阻止默认右键菜单selectedNode.value node.data; // 保存当前节点showContextMenu.value true; // 显示自定义右键菜单contextMenuPosition.value { top: event.clientY, left: event.clientX }; // 设置菜单显示位置
};
//重命名
const renameNode () {if (selectedNode.value) {const newName prompt(请输入新名称, selectedNode.value.label);if (newName) {selectedNode.value.label newName; // 修改节点名称}}showContextMenu.value false; // 隐藏菜单
};
//删除
const deleteNode () {if (selectedNode.value) {const confirmDelete confirm(确定删除 ${selectedNode.value.label} 吗);if (confirmDelete) {removeFile()}}showContextMenu.value false; // 隐藏菜单
};
/scripttemplatediv classcontainerheader classheader!-- 新建文件和文件夹的按钮 --el-button typeprimary clickcreateFolder新建文件夹/el-buttonel-button typeprimary clickcreateFile新建文件/el-buttonel-button typeprimary clickremoveFile删除文件/文件夹/el-button/headerdiv classmainaside classasideel-treestylemax-width: 600px:datadata:propsdefaultPropsnode-clickhandleNodeClicknode-contextmenuhandleContextMenu!-- 使用 render-content 插槽自定义节点显示 --template #default{ node, data }span!-- 判断节点类型来动态显示图标 --el-icon v-ifdata.type folderFolder //el-iconel-icon v-ifdata.type fileFiles //el-icon{{ data.label }}/span/template/el-treedivclassdropdownv-ifshowContextMenu:style{position: absolute,top: contextMenuPosition.top px,left: contextMenuPosition.left px,}ul slotdropdownli clickrenameNode重命名/lili clickdeleteNode删除/li/ul/div/asidediv classcontent!-- 内容区域 --/div/div/div
/templatestyle scoped
.container {width: 100%;height: 100%;display: flex;flex-direction: column;
}.header {height: 60px;border:1px solid #ccc;
}.main {flex: 1;display: flex;
}.aside {width: 200px;border-right: 1px solid #ccc;
}.content {flex: 1;padding: 10px;
}
.dropdown {position: absolute;background-color: #fff;padding:20px;border-radius: 5px;border:1px solid #ccc;
}
/style