-
一、搜索前端技术需求Nuxt.js 是 Vue.js 生态下专注解决 SEO 问题的服务端渲染(SSR)框架,专为需搜索引擎优化的前端场景设计,可兼顾 Vue 开发体验与服务端渲染优势。其核心价值在于破解 Vue 客户端渲染的 SEO 短板 —— 客户端渲染中搜索引擎爬虫难以解析 JS 生成的内容,而 Nuxt.js 部署于 Node.js,接收请求后先从服务端获取数据,完成 HTML 渲染再响应给浏览器,生成的完整 DOM 能被爬虫高效抓取。1.1 需求描述采用vue.js开发搜索界面则SEO不友好,需要解决SEO的问题 1.2 了解SEOSEO,也就是搜索引擎优化的逻辑,其实是非常简单的。这就像是在大学里的学生会主席,你要让投票者给你更多的选票。那么,你需要先「自我优化」,无论是外表还是能力;此外,你还需获得更多意见领袖的推荐,才可以让更多普通选民支持你。同样的,你要让搜索引擎在无数的文章,把你的文章排到前面。你首先需要先做:1. 内部优化:也就是提高文章本身的质量2. 外部优化:也就是让你的文章曝光在更多权威网站上总结:seo是网站为了提高自已的网站排名,获得更多的流量,对网站的结构及内容进行调整优化,以便搜索引擎 (百度,google等)更好抓取到更优质的网站的内容。下图是搜索引擎爬取网站页面的大概流程图:(搜索引擎的工作流程很复杂,下图只是简单概括) 从上图可以看到SEO是网站自己为了方便spider抓取网页而作出的网页内容优化,常见的SEO方法比如:对url链接的规范化,多用restful风格的url,多用静态资源url;注意title、keywords的设置。由于spider对javascript支持不好,对于网页跳转用href标签。 。。。 1.3 服务端渲染和客户端渲染采用什么技术有利于SEO?要解答这个问题需要理解服务端渲染和客户端渲染。什么是服务端渲染?我们用传统的servlet开发来举例:浏览器请求servlet,servlet在服务端生成html响应给浏览器,浏览器展示html的内容,这个过程就是服务端渲染,如下图: 服务端渲染的特点:在服务端生成 html 网页的dom元素。客户端(浏览器)只负责显示dom元素内容。当初随着web2.0的到来,AJAX技术兴起,出现了客户端渲染:客户端(浏览器) 使用AJAX向服务端发起http请 求,获取到了想要的数据,客户端拿着数据开始渲染html网页,生成Dom元素,并最终将网页内容展示给用户, 如下图: 客户端渲染的特点:在服务端只是给客户端响应的了数据,而不是html网页客户端(浏览器)负责获取服务端的数据生成Dom元素。两种方式各有什么优缺点?客户端渲染:缺点 不利于网站进行SEO,因为网站大量使用javascript技术,不利于spider抓取网页。优点 客户端负责渲染,用户体验性好,服务端只提供数据不用关心用户界面的内容,有利于提高服务端的开发效率。适用场景 对SEO没有要求的系统,比如后台管理类的系统,如电商后台管理,用户管理等。 服务端渲染:优点有利于SEO,网站通过href的url将spider直接引到服务端,服务端提供优质的网页内容给spider。缺点服务端完成一部分客户端的工作,通常完成一个需求需要修改客户端和服务端的代码,开发效率低,不利于系统的稳定性。适用场景 对SEO有要求的系统,比如:门户首页、商品详情页面等二、 Nuxt.js介绍2.1 Nuxt.js介绍移动互联网的兴起促进了web前后端分离开发模式的发展,服务端只专注业务,前端只专注用户体验,前端大量运 用的前端渲染技术,比如流行的vue.js、react框架都实现了功能强大的前端渲染。但是,对于有SEO需求的网页如果使用前端渲染技术去开发就不利于SEO了,有没有一种即使用vue.js、react的前 端技术也实现服务端渲染的技术呢?其实,对于服务端渲染的需求,vue.js、react这样流行的前端框架提供了服务 端渲染的解决方案。 从上图可以看到: react框架提供next.js实现服务端渲染。 vue.js框架提供Nuxt.js实现服务端渲染2.2 Nuxt.js工作原理下图展示了从客户端请求到Nuxt.js进行服务端渲染的整体的工作流程 用户打开浏览器,输入网址请求到Node.js部署在Node.js的应用Nuxt.js接收浏览器请求,并请求服务端获取数据Nuxt.js获取到数据后进行服务端渲染Nuxt.js将html网页响应给浏览器Nuxt.js使用了哪些技术?Nuxt.js使用Vue.js+webpack+Babel三大技术框架/组件,如下图: Babel 是一个js的转码器,负责将ES6的代码转成浏览器识别的ES5代码。 Webpack是一个前端工程打包工具。 Vue.js是一个优秀的前端框架。Nuxt.js的特性有哪些?基于 Vue.js自动代码分层服务端渲染强大的路由功能,支持异步数据静态文件服务ES6/ES7 语法支持打包和压缩 JS 和 CSSHTML头部标签管理本地开发支持热加载集成ESLint支持各种样式预处理器: SASS、LESS、 Stylus等等总结Nuxt.js 是 Vue.js 生态下专注解决 SEO 问题的服务端渲染(SSR)框架,专为需搜索引擎优化的前端场景设计,可兼顾 Vue 开发体验与服务端渲染优势。其核心价值在于破解 Vue 客户端渲染的 SEO 短板 —— 客户端渲染中搜索引擎爬虫难以解析 JS 生成的内容,而 Nuxt.js 部署于 Node.js,接收请求后先从服务端获取数据,完成 HTML 渲染再响应给浏览器,生成的完整 DOM 能被爬虫高效抓取。架构上以 “约定优于配置” 为核心,基于 Vue.js、Webpack、Babel 构建,具备自动路由生成、代码分层等特性,无需手动配置路由,支持异步数据加载与 HTML 头部标签管理。同时内置 SEO 优化能力,可自动生成 meta 标签、XML 站点地图,规范 URL 处理,比手动配置更高效。适用场景聚焦内容密集型网站(如博客、商品详情页)及 SEO 关键项目,能平衡开发效率与性能,既保留前端开发灵活性,又通过服务端渲染提升页面收录与排名表现。
-
webpack入门使用vue.js开发大型应用需要使用webpack打包工具,本节研究webpack的使用方法。1.3.1 webpack介绍 Webpack 是一个前端资源的打包工具,它可以将js、image、css等资源当成一个模块进行打包。从图中我们可以看出,Webpack 可以将js、css、png等多种静态资源 进行打包,使用webpack有什么好处呢?1 、模块化开发程序员在开发时可以分模块创建不同的js、 css等小文件方便开发,最后使用webpack将这些小文件打包成一个文件,减少了http的请求次数。webpack可以实现按需打包,为了避免出现打包文件过大可以打包成多个文件。2 、 编译typescript、ES6等高级js语法随着前端技术的强大,开发中可以使用javascript的很多高级版本,比如:typescript、ES6等,方便开发, webpack可以将打包文件转换成浏览器可识别的js语法。3 、CSS预编译webpack允许在开发中使用Sass 和 Less等原生CSS的扩展技术,通过sass-loader、less-loader将Sass 和 Less的 语法编译成浏览器可识别的css语法。webpack的缺点:1 、配置有些繁琐2 、文档不丰富1.3.2 安装webpack1.3.2.1 安装Node.jswebpack基于node.js运行,首先需要安装node.js。 为什么会有node.js?传统意义上的 JavaScript 运行在浏览器上,Chrome 使用的 JavaScript 引擎是 V8,Node.js 是一个运行在服务端的框架,它的底层就使用了 V8 引擎,这样就可以使用javascript去编写一些服务端的程序,这样也就实现了用javaScript去开发 Apache + PHP 以及 Java Servlet所开发的服务端功能,这样做的好处就是前端和后端都采用javascript,即开发一份js程序即可以运行在前端也可以运行的服务端,这样比一个应用使用多种语言在开发效率上要高,不过node.js属于新兴产品,一些公司也在尝试使用node.js完成一些业务领域,node.js基于V 8 引擎,基于事件驱动机制,在特定领域性能出色,比如用node.js实现消息推送、状态监控等的业务功能非常合适。下边我们去安装Node.js:1 、下载对应你系统的Node.js版本:https://nodejs.org/en/download/ 推荐下载LTS版本,本教程安装 9 .4.0。2 、选安装目录进行安装默认即可安装完成检查PATH环境变量是否设置了node.js的路径。3 、测试在命令提示符下输入命令node ‐v会显示当前node的版本1 .3.2.2 安装NPM1 、自动安装NPMnpm全称Node Package Manager,他是node包管理和分发的工具,使用NPM可以对应用的依赖进行管理,NPM的功能和服务端项目构建工具maven差不多,我们通过npm 可以很方便地下载js库,打包js文件。node.js已经集成了npm工具,在命令提示符输入 npm -v 可查看当前npm版本 2 、设置包路径包路径就是npm从远程下载的js包所存放的路径。使用 npm config ls 查询NPM管理包路径(NPM下载的依赖包所存放的路径) NPM默认的管理包路径在C:/用户/[用户名]/AppData/Roming/npm/node_meodules,为了方便对依赖包管理,我 们将管理包的路径设置在单独的地方,本教程将安装目录设置在node.js的目录下,创建npm_modules和 npm_cache,执行下边的命令:本教程安装node.js在D:\Program Files\nodejs下所以执行命令如下:npm config set prefix "C:\Program Files\nodejs\npm_modules"npm config set prefix "D:\nodejs\npm_modules" (更改本地仓库的位置)npm config set cache "c:\Program Files\nodejs\npm_cache"npm config set cache "D:\nodejs\npm_cache" (更改本地仓库的缓存位置)此时再使用 npm config ls 查询NPM管理包路径发现路径已更改 npm config set registry http://registry.npm.taobao.org 配置到此为止结束。3 、安装cnpmnpm默认会去国外的镜像去下载js包,在开发中通常我们使用国内镜像,这里我们使用淘宝镜像下边我们来安装cnpm:有时我们使用npm下载资源会很慢,所以我们可以安装一个cnmp(淘宝镜像)来加快下载速度。输入命令,进行全局安装淘宝镜像。npm install -g cnpm --registry=http://registry.npm.taobao.org安装后,我们可以使用以下命令来查看cnpm的版本cnpm -v nrm ls 查看镜像已经指向taobao 使nrm use XXX切换 镜像如果nrm没有安装则需要进行全局安装:cnpm install -g nrm4 、非连网环境安装cnpm从本小节第 3 步开始就需要连网下载npm包,如果你的环境不能连网在老师的资料文件下有已经下载好的webpack相关包,下边是安装方法。1 )配置环境变量NODE_HOME = D:\Program Files\nodejs (node.js安装目录)在PATH变量中添加:%NODE_HOME%;%NODE_HOME%\npm_modules;2 )找到npm包路径根据上边的安装说明npm包路径被设置到了node.js安装目录下的npm_modules目录。可以使用npm config ls查看。拷贝课程资料中的 npm_modules.zip到node.js安装目录,并解压npm_modules.zip覆盖本目录下的 npm_modules文件夹。3 )完成上边步骤测试cnpm -v1.3.2.3 安装webpack1 、连网安装webpack安装分为本地安装和全局安装:本地安装:仅将webpack安装在当前项目的node_modules目录中,仅对当前项目有效。全局安装:将webpack安装在本机,对所有项目有效,全局安装会锁定一个webpack版本,该版本可能不适用某个项目。全局安装需要添加 -g 参数。进入webpacktest测试目录目录,运行:1 )本地安装:只在我的项目中使用webpack,需要进行本地安装,因为项目和项目所用的webpack的版本不一样。本地安装就会将webpack的js包下载到项目下的npm_modeuls目录下。在门户目录下创建webpack测试目录webpacktest01:npm install --save-dev webpack 或 cnpm install --save-dev webpacknpm install --save-dev webpack-cli (4.0以后的版本需要安装webpack-cli)2 )全局安装加-g,如下:全局安装就将webpack的js包下载到npm的包路径下。npm install webpack -g 或 cnpm install webpack -g3 )安装webpack指定的版本:本教程使用webpack3.6.0,安装webpack3.6.0:进入webpacktest测试目录,运行:cnpm install --save-dev webpack@3.6.全局安装:npm install webpack@3.6.0 -g或 cnpm install webpack@3.6.0 -g2 、非连网安装参考上边 “非连网环境安装cnpm”描述,将课程资料中的 npm_modules.zip到node.js安装目录,并解压 npm_modules.zip覆盖本目录下的npm_modules文件夹。说明:已执行 “非连网环境安装cnpm”下的操作不用重复执行。测试:在cmd状态输入webpack,出现如下提示说明 webpack安装成功 总结Webpack 是基于 Node.js 的现代前端静态模块打包器,核心功能是将 JS、CSS、图片等多种资源视作模块,通过打包优化项目结构与性能,是 Vue 等框架开发大型应用的核心工具。其核心优势显著:支持模块化开发,可将代码拆分为小模块便于维护,打包后减少 HTTP 请求次数,还能按需拆分避免文件过大;通过 loader 机制编译 ES6、TypeScript 等高级语法及 Sass、Less 等 CSS 预编译语言,适配浏览器兼容;搭配插件生态可实现热模块替换等功能,提升开发效率。安装需先部署 Node.js(含 npm 包管理工具),可配置淘宝镜像(cnpm)加速下载,支持全局与本地两种安装方式,本地安装更适配多项目版本差异。虽存在配置繁琐、早期文档不足的缺点,但凭借强大的资源处理与优化能力,仍是前端工程化开发的主流工具。
-
一.webpack和vite的区别1.构建速度不同Webpack: Webpack的构建速度相对较慢,尤其在大型项目中,因为它需要分析整个依赖图,进行多次文件扫描和转译。Vite: Vite以开发模式下的极速构建著称。它利用ES模块的特性,只有在真正需要时才编译文,而不是整个项目。这使得它在开发环境下几乎是即时的。2.开发模式不同Webpack: Webpack通常使用热模块替换(HMR)来实现快速开发模式,但配置相对复杂。Vite: 采用了基于ES Module的开发服务器,只有在需要时才会编译对应的模块,大幅度提升了开发环境的响应速度。3.配置复杂度不同Webpack: Webpack的配置相对复杂,特别是在处理不同类型的资源和加载器时。Vite: Vite在设计上更注重开箱即用,大部分场景下用户无需自己写配置文件,但同时也支持自定义配置,使其适用于复杂项目。4.插件生态不同Webpack: Webpack拥有庞大的插件生态系统,适用于各种不同的需求。Vite: Vite也有相当数量的插件,但相对较小,因为它的开发模式和构建方式减少了对一些传统插件的需求。5.编译方式不同Webpack: webpack在编译过程中,会将所有模块打包为一个bundle.js文件,然后再运行这个文件。Vite: 没有打包的步骤,它利用了浏览器的ES Module Imports特性,只有在真正需要时才编译文件。6.应用场景不同Webpack: 适用于复杂的大型项目,特别是需要大量自定义配置和复杂构建管道的项目。Vite: 更适用于小到中型项目,或者需要快速开发原型和小型应用的场景。二.为什么vite启动速度比webpack快?1、开发模式的差异12345在开发环境中,Webpack 是先打包再启动开发服务器,而 Vite 则是直接启动,然后再按需编译依赖文件。(大家可以启动项目后检查源码 Sources 那里看到) 这意味着,当使用 Webpack 时,所有的模块都需要在开发前进行打包,这会增加启动时间和构建时间。 而 Vite 则采用了不同的策略,它会在请求模块时再进行实时编译,这种按需动态编译的模式极大地缩短了编译时间,特别是在大型项目中,文件数量众多,Vite 的优势更为明显。Webpack启动Vite启动2、对ES Modules的支持现代浏览器本身就支持 ES Modules,会主动发起请求去获取所需文件。Vite充分利用了这一点,将开发环境下的模块文件直接作为浏览器要执行的文件,而不是像 Webpack 那样先打包,再交给浏览器执行。这种方式减少了中间环节,提高了效率。什么是ES Modules?通过使用 export 和 import 语句,ES Modules 允许在浏览器端导入和导出模块。当使用 ES Modules 进行开发时,开发者实际上是在构建一个依赖关系图,不同依赖项之间通过导入语句进行关联。主流浏览器(除IE外)均支持ES Modules,并且可以通过在 script 标签中设置 type="module"来加载模块。默认情况下,模块会延迟加载,执行时机在文档解析之后,触发DOMContentLoaded事件前。3、底层语言的差异Webpack 是基于 Node.js 构建的,而 Vite 则是基于 esbuild 进行预构建依赖。esbuild 是采用 Go 语言编写的,Go 语言是纳秒级别的,而 Node.js 是毫秒级别的。因此,Vite 在打包速度上相比Webpack 有 10-100 倍的提升。什么是预构建依赖?预构建依赖通常指的是在项目启动或构建之前,对项目中所需的依赖项进行预先的处理或构建。这样做的好处在于,当项目实际运行时,可以直接使用这些已经预构建好的依赖,而无需再进行实时的编译或构建,从而提高了应用程序的运行速度和效率。4、热更新的处理在 Webpack 中,当一个模块或其依赖的模块内容改变时,需要重新编译这些模块。而在 Vite 中,当某个模块内容改变时,只需要让浏览器重新请求该模块即可,这大大减少了热更新的时间。总结总的来说,Vite 之所以比 Webpack 快,主要是因为它采用了不同的开发模式、充分利用了现代浏览器的 ES Modules 支持、使用了更高效的底层语言,并优化了热更新的处理。这些特点使得 Vite在大型项目中具有显著的优势,能够快速启动和构建,提高开发效率。
-
vxe-table 如何在单元格内容渲染成可点击复制的文本通过 cellRender.name='VxeText',设置参数 clickToCopy=true 就可以开启文本复制功能,点击复制回会自动将文本复制到剪贴板<template> <div> <vxe-grid v-bind="gridOptions"></vxe-grid> </div> </template> <script setup> import { reactive } from 'vue' const roleCellRender = reactive({ name: 'VxeText', props: { clickToCopy: true } }) const addressCellRender = reactive({ name: 'VxeText', props: { clickToCopy: true, status: 'error' } }) const gridOptions = reactive({ border: true, showOverflow: true, columns: [ { type: 'seq', width: 70 }, { field: 'name', title: 'Name', minWidth: 200 }, { field: 'role', title: 'Role', width: 120, cellRender: roleCellRender }, { field: 'address', title: 'Address', width: 300, cellRender: addressCellRender } ], data: [ { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' }, { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' }, { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' }, { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' } ] }) </script>
-
vxe-tree-select 树形下拉框当使用懒加载数据时如何回显当使用懒加载或者当某个选项被删除时,显示自定义回显;比如使用懒加载树列表,由于数据未被加载,这时候已选的数据就不能被回显,导致显示了 value值,而不是 label。还有一种场景就是组织架构人员选择,当选择某个人员后,可能人员变动离职,数据被删掉了,这个时候也无法回显。那么怎么解决以上几种情况,解决方式也很简单官网:https://vxeui.comgithub:https://github.com/x-extends/vxe-pc-uigitee:https://gitee.com/x-extends/vxe-pc-ui问题无法显示对应的label解决效果比如以下懒加载树选择,所有的子项都没有点击加载,也可以正确回显label代码可以通过设置 lazy-options 来将指定节点放入用来回显,将不存在选项的数据额外放到这里,就可以实现自动回显<template> <div> <vxe-tree-select v-model="val1" :options="treeList" :lazy-options="lazyList" :treeConfig="treeConfig" multiple clearable></vxe-tree-select> </div> </template> <script setup> import { ref, reactive } from 'vue' const val1 = ref(['4-2']) const treeConfig = reactive({ lazy: true, loadMethod ({ node }) { return getNodeListApi(node) } }) const treeList = ref([ { label: '节点2', value: '2', hasChild: true }, { label: '节点3', value: '3', hasChild: true }, { label: '节点4', value: '4', hasChild: true }, { label: '节点5', value: '5', hasChild: false } ]) const lazyList = ref([ { label: '节点4-2', value: '4-2' } ]) let treeKey = 1 const getNodeListApi = (node) => { return new Promise(resolve => { // 模拟后端接口 setTimeout(() => { resolve([ { label: `节点${node.value}-${treeKey}`, value: `节点${node.value}-${treeKey}`, hasChild: Math.random() * 10 < 6 }, { label: `节点${node.value}-${treeKey + 1}`, value: `节点${node.value}-${treeKey + 1}`, hasChild: Math.random() * 10 < 6 } ]) treeKey += 2 }, 500) }) } </script>
-
一、Vue.js 简介Vue.js 是一套用于构建用户界面的渐进式框架,由尤雨溪创建。与其他大型框架不同,Vue 被设计为可以自底向上逐层应用,核心库只关注视图层,易于上手,也便于与第三方库或既有项目整合。Vue 的核心特性:响应式数据绑定:自动追踪依赖,更新DOM组件系统:可复用、可组合的UI组件虚拟DOM:高效的DOM更新策略丰富的生态系统:Vue Router、Vuex、Vue CLI等工具支持二、快速开始1. 安装方式CDN引入(适合快速原型开发):html <script src="https://cdn.jsdelivr.net/npm/vue@3.2.31/dist/vue.global.js"></script>使用Vue CLI(推荐生产环境使用):bash npm install -g @vue/clivue create my-projectcd my-projectnpm run serve2. 基础示例html <div id="app"> <h1>{{ message }}</h1> <button @click="reverseMessage">反转消息</button></div><script>const { createApp } = VuecreateApp({ data() { return { message: 'Hello Vue!' } }, methods: { reverseMessage() { this.message = this.message.split('').reverse().join('') } }}).mount('#app')</script>三、核心概念详解1. 模板语法Vue 使用基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层组件实例的数据。html <div id="bind-attribute"> <span v-bind:title="message">悬停查看动态绑定的提示信息!</span> <!-- 缩写 --> <span :title="message">简写形式</span></div>2. 计算属性和侦听器计算属性:js computed: { reversedMessage() { return this.message.split('').reverse().join('') }}侦听器:js watch: { message(newVal, oldVal) { console.log(`消息从"${oldVal}"变为"${newVal}"`) }}3. 条件渲染和列表渲染v-if:html <p v-if="seen">现在你看到我了</p><p v-else>你看不到我了</p>v-for:html <ul> <li v-for="(item, index) in items" :key="item.id"> {{ index }} - {{ item.text }} </li></ul>4. 组件系统组件定义:js // 定义一个名为 button-counter 的新组件app.component('button-counter', { data() { return { count: 0 } }, template: ` <button @click="count++"> 点了 {{ count }} 次! </button> `})组件使用:html <div id="components-demo"> <button-counter></button-counter></div>四、Vue 3 新特性1. Composition APIjs import { ref, computed, onMounted } from 'vue'export default { setup() { const count = ref(0) const double = computed(() => count.value * 2) function increment() { count.value++ } onMounted(() => { console.log('组件已挂载') }) return { count, double, increment } }}2. Teleport 传送门html <teleport to="body"> <div class="modal" v-if="showModal"> 我是一个模态框! </div></teleport>3. 片段(Fragments)html <template> <header>...</header> <main>...</main> <footer>...</footer></template>五、生态系统1. Vue Routerjs import { createRouter, createWebHistory } from 'vue-router'const routes = [ { path: '/', component: Home }, { path: '/about', component: About }]const router = createRouter({ history: createWebHistory(), routes})2. Vuex/Pinia 状态管理Vuex示例:js const store = createStore({ state() { return { count: 0 } }, mutations: { increment(state) { state.count++ } }})3. Vue CLI 和 Vite使用Vite创建项目:bash npm init vite@latest my-vue-app --template vuecd my-vue-appnpm installnpm run dev六、最佳实践组件设计原则:单一职责原则合理的props/emit设计可复用性考虑性能优化:合理使用v-if和v-show列表渲染使用key组件懒加载代码组织:按功能而非类型组织代码使用Composition API提取可复用逻辑统一代码风格Vue.js 以其简洁的API设计、灵活的组件系统和活跃的社区,已成为现代Web开发的主流选择之一。无论是小型项目还是大型企业应用,Vue都能提供高效的开发体验和出色的性能表现。
-
vxe-table 树表格拖拽排序,支持拖拽到空节点,直接拖拽成子级;通过 row-drag-config.isToChildDrag 启用便捷拖拽成子节点,拖拽的同时按住 Ctrl 键可以自动拖放到该节点的子级 通过 row-drag-config.isToChildDrag 启用便捷拖拽成子节点,拖拽的同时按住 Ctrl 键可以自动拖放到该节点的子级<template> <div> <vxe-grid v-bind="gridOptions"></vxe-grid> </div> </template> <script setup> import { reactive } from 'vue' const gridOptions = reactive({ border: true, rowConfig: { useKey: true, drag: true }, rowDragConfig: { isCrossDrag: true, isSelfToChildDrag: true, isToChildDrag: true }, columnConfig: { useKey: true }, treeConfig: { transform: true, rowField: 'id', parentField: 'parentId' }, columns: [ { type: 'seq', width: 70 }, { field: 'name', title: 'Name', minWidth: 300, treeNode: true, dragSort: true }, { field: 'size', title: 'Size' }, { field: 'type', title: 'Type' }, { field: 'date', title: 'Date' } ], data: [ { id: 10000, parentId: null, name: 'Test1', type: 'mp3', size: 1024, date: '2020-08-01' }, { id: 10050, parentId: null, name: 'Test2', type: 'mp4', size: 0, date: '2021-04-01' }, { id: 24300, parentId: 10050, name: 'Test3', type: 'avi', size: 1024, date: '2020-03-01' }, { id: 20045, parentId: 24300, name: 'Test4', type: 'html', size: 600, date: '2021-04-01' }, { id: 10053, parentId: 24300, name: 'Test5', type: 'avi', size: 0, date: '2021-04-01' }, { id: 24330, parentId: 10053, name: 'Test6', type: 'txt', size: 25, date: '2021-10-01' }, { id: 21011, parentId: 10053, name: 'Test7', type: 'pdf', size: 512, date: '2020-01-01' }, { id: 22200, parentId: 10053, name: 'Test8', type: 'js', size: 1024, date: '2021-06-01' }, { id: 23666, parentId: null, name: 'Test9', type: 'xlsx', size: 2048, date: '2020-11-01' }, { id: 23677, parentId: 23666, name: 'Test10', type: 'js', size: 1024, date: '2021-06-01' }, { id: 23671, parentId: 23677, name: 'Test11', type: 'js', size: 1024, date: '2021-06-01' }, { id: 23672, parentId: 23677, name: 'Test12', type: 'js', size: 1024, date: '2021-06-01' }, { id: 23688, parentId: 23666, name: 'Test13', type: 'js', size: 1024, date: '2021-06-01' }, { id: 23681, parentId: 23688, name: 'Test14', type: 'js', size: 1024, date: '2021-06-01' }, { id: 23682, parentId: 23688, name: 'Test15', type: 'js', size: 1024, date: '2021-06-01' }, { id: 24555, parentId: null, name: 'Test16', type: 'avi', size: 224, date: '2020-10-01' }, { id: 24566, parentId: 24555, name: 'Test17', type: 'js', size: 1024, date: '2021-06-01' }, { id: 24577, parentId: 24555, name: 'Test18', type: 'js', size: 1024, date: '2021-06-01' } ] }) </script> 转载自https://www.cnblogs.com/qaz666/p/18598387
-
vxe-table 树结构单元格选取与复制粘贴,通过 tree-config.transform 使用树形表格 <template> <div> <vxe-table border show-overflow keep-source height="600" :column-config="columnConfig" :tree-config="treeConfig" :mouse-config="mouseConfig" :area-config="areaConfig" :edit-config="editConfig" :clip-config="clipConfig" :keyboard-config="keyboardConfig" :data="tableData"> <vxe-column type="seq" width="80"></vxe-column> <vxe-column field="name" title="名称" min-width="300" tree-node :edit-render="{ name: 'input' }"></vxe-column> <vxe-column field="size" title="大小" width="140" :edit-render="{ name: 'input' }"></vxe-column> <vxe-column field="type" title="类型" width="140" :edit-render="{ name: 'input' }"></vxe-column> <vxe-column field="createBy" title="创建人" width="200" :edit-render="{ name: 'input' }"></vxe-column> <vxe-column field="updateDate" title="修改时间" width="200" :edit-render="{ name: 'input' }"></vxe-column> <vxe-column field="createDate" title="创建时间" width="200" :edit-render="{ name: 'input' }"></vxe-column> </vxe-table> </div> </template> <script> export default { data () { const tableData = [ { id: 10000, parentId: null, name: '文件1.xlsx', type: 'xlsx', size: 1024, createBy: '王五', updateDate: '2020-09-11', createDate: '2020-08-01' }, { id: 10050, parentId: null, name: '部署目录', type: '', size: 0, createBy: '老六', updateDate: '2020-08-01', createDate: '2021-04-01' }, { id: 24300, parentId: 10050, name: '菜单配置.avi', type: 'avi', size: 1024, createBy: '小芳', updateDate: '2020-10-24', createDate: '2020-03-01' }, { id: 20045, parentId: 24300, name: '角色说明.html', type: 'html', size: 600, createBy: '老徐', updateDate: '2020-08-01', createDate: '2021-04-01' }, { id: 10053, parentId: 24300, name: '权限配置.avi', type: 'avi', size: 0, createBy: '老胡', updateDate: '', createDate: '2021-04-01' }, { id: 24330, parentId: 10053, name: '部署秘钥.txt', type: 'txt', size: 25, createBy: '张三', updateDate: '2020-09-11', createDate: '2021-10-01' }, { id: 21011, parentId: 10053, name: '流程文档。pdf', type: 'pdf', size: 512, createBy: '老张', updateDate: '2020-08-01', createDate: '2020-01-01' }, { id: 22200, parentId: 10053, name: '解决 bug 文件.js', type: 'js', size: 1024, createBy: '小刘', updateDate: '2020-10-24', createDate: '2021-06-01' }, { id: 23666, parentId: null, name: '发版目录', type: '', size: 2048, createBy: '老刘', updateDate: '2020-02-18', createDate: '2020-11-01' }, { id: 23677, parentId: 23666, name: '替换问题文件.js', type: 'js', size: 1024, createBy: '老冯', updateDate: '2020-09-11', createDate: '2021-06-01' }, { id: 23671, parentId: 23677, name: '发布流程.avi', type: 'avi', size: 1024, createBy: '小牛', updateDate: '2020-08-01', createDate: '2021-06-01' }, { id: 23672, parentId: 23677, name: '配置流程.mp4', type: 'mp4', size: 1024, createBy: '李四', updateDate: '2020-02-09', createDate: '2021-06-01' }, { id: 23688, parentId: 23666, name: '测试流程.mp4', type: 'mp4', size: 1024, createBy: '小三', updateDate: '2020-10-24', createDate: '2021-06-01' }, { id: 23681, parentId: 23688, name: '问题记录.txt', type: 'txt', size: 1024, createBy: '小李', updateDate: '2020-08-01', createDate: '2021-06-01' }, { id: 23682, parentId: 23688, name: '发布说明.html', type: 'html', size: 1024, createBy: '小徐', updateDate: '2020-02-18', createDate: '2021-06-01' }, { id: 24555, parentId: null, name: '资源目录', type: '', size: 224, createBy: '小小', updateDate: '2020-08-01', createDate: '2020-10-01' }, { id: 24566, parentId: 24555, name: '铃声文件.mp3', type: 'mp3', size: 1024, createBy: '老八', updateDate: '2020-02-29', createDate: '2021-06-01' }, { id: 24577, parentId: 24555, name: '上线人员列表.xlsx', type: 'xlsx', size: 1024, createBy: '小红', updateDate: '2020-08-01', createDate: '2021-06-01' } ] const columnConfig = { resizable: true } const treeConfig = { transform: true, rowField: 'id', parentField: 'parentId' } const mouseConfig = { area: true // 是否开启区域选取 } const areaConfig = { multiple: true // 是否启用多区域选取功能 } const editConfig = { mode: 'cell', trigger: 'dblclick', showStatus: true } const clipConfig = { isDeepPaste: true // 是否深层粘贴,用于树结构,启用后粘贴时会覆盖到子级数据进行粘贴 } const keyboardConfig = { isClip: true, isArrow: true, isShift: true, isTab: true, isEnter: true, isEdit: true, isDel: true, isEsc: true, isFNR: true // 是否开启查找与替换 } return { tableData, columnConfig, treeConfig, mouseConfig, areaConfig, editConfig, clipConfig, keyboardConfig } } } </script> 转载自https://www.cnblogs.com/qaz666/p/18578665
-
<template> <div> <vxe-table border header-align="center" align="left" :data="tableData"> <vxe-column type="seq" width="70"></vxe-column> <vxe-column field="name" title="Name"></vxe-column> <vxe-column field="sex" title="Sex"></vxe-column> <vxe-column field="age" title="Age"></vxe-column> </vxe-table> </div> </template> <script> export default { data () { const tableData = [ { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' }, { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' }, { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' }, { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' } ] return { tableData } } } </script> 转载自https://www.cnblogs.com/qaz666/p/18566295
-
<template> <div> <vxe-upload v-model="imgList" mode="image" multiple show-progress :upload-method="uploadMethod"></vxe-upload> </div> </template> <script> import axios from 'axios' export default { data () { const imgList = [] const uploadMethod = ({ file }) => { const formData = new FormData() formData.append('file', file) return axios.post('/api/pub/upload/single', formData).then((res) => { return { ...res.data } }) } return { imgList, uploadMethod } } } </script>转载自https://www.cnblogs.com/qaz666/p/18563025
-
<template> <div> <vxe-button status="success" @click="resultEvent">获取列</vxe-button> <vxe-table border ref="tableRef" :column-config="columnConfig" :data="tableData"> <vxe-column field="name" title="Name"></vxe-column> <vxe-column field="role" title="Role"></vxe-column> <vxe-column field="sex" title="Sex"></vxe-column> <vxe-column field="age" title="Age"></vxe-column> <vxe-column field="address" title="Address"></vxe-column> </vxe-table> </div> </template> <script> export default { data () { const tableData = [ { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' }, { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' }, { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' }, { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' } ] const columnConfig = { useKey: true, drag: true } return { tableData, columnConfig } }, methods: { resultEvent () { const $table = this.$refs.tableRef if ($table) { const { visibleColumn } = $table.getTableColumn() console.log(visibleColumn) } } } } </script> 转载自https://www.cnblogs.com/qaz666/p/18562144
-
<template> <div> <vxe-table border ref="tableRef" :row-config="rowConfig" :column-config="columnConfig" :data="tableData"> <vxe-column field="name" title="Name" drag-sort></vxe-column> <vxe-column field="role" title="Role" drag-sort></vxe-column> <vxe-column field="sex" title="Sex"></vxe-column> <vxe-column field="age" title="Age"></vxe-column> <vxe-column field="address" title="Address" drag-sort></vxe-column> </vxe-table> </div> </template> <script> export default { data () { const tableData = [ { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' }, { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' }, { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' }, { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' } ] const rowConfig = { useKey: true, drag: true } const columnConfig = { useKey: true } return { tableData, rowConfig, columnConfig } } } </script> 转载自https://www.cnblogs.com/qaz666/p/18562136
-
在 vxe-table 中使用 vxe-grid 渲染表格,当配置式不能满足需求时,。需要使用自定义插槽模板来自定义业务需求,实现更灵活的功能。vxe-grid 支持多种自定义方式,可以使用插槽模板,也可以使用插槽来自定义模板。自定义单元格模板 <template> <div> <vxe-grid v-bind="gridOptions"> <template #imgUrl_default="{ row }"> <vxe-image :src="row.imgUrl" width="36" height="30"></vxe-image> </template> <template #name_default="{ row }"> <vxe-button mode="text" @click="openDetail(row)">点击{{ row.name }}</vxe-button> </template> <template #sex_default="{ row }"> <span>{{ formatSex(row) }}</span> </template> <template #address_default="{ row }"> <vxe-image src="https://vxeui.com/resource/img/546.gif" width="36" height="30"></vxe-image> <span>{{ row.address }}</span> <vxe-image src="https://n.sinaimg.cn/sinacn17/w120h120/20180314/89fc-fyscsmv5911424.gif" width="30" height="30"></vxe-image> </template> </vxe-grid> </div> </template> <script setup> import { reactive } from 'vue' import { VxeUI } from 'vxe-table' const gridOptions = reactive({ border: true, showOverflow: true, columns: [ { type: 'seq', width: 70 }, { field: 'imgUrl', title: 'imgUrl', slots: { default: 'imgUrl_default' } }, { field: 'name', title: 'Name', slots: { default: 'name_default' } }, { title: 'Group1', children: [ { field: 'sex', title: 'Sex', slots: { default: 'sex_default' } }, { field: 'num', title: 'Number' }, { field: 'age', title: 'Age' } ] }, { field: 'address', title: 'Address', width: 200, slots: { default: 'address_default' } } ], data: [ { id: 10001, name: 'Test1', role: 'Develop', sex: '0', age: 28, num: 234, imgUrl: 'https://vxeui.com/resource/img/fj577.jpg', address: 'test abc' }, { id: 10002, name: 'Test2', role: 'Test', sex: '1', age: 22, num: 34, imgUrl: 'https://vxeui.com/resource/img/fj581.jpeg', address: 'Guangzhou' }, { id: 10003, name: 'Test3', role: 'PM', sex: '0', age: 32, num: 12, imgUrl: 'https://vxeui.com/resource/img/fj581.jpeg', address: 'Shanghai' } ] }) const formatSex = (row) => { return row.sex === '1' ? '男' : '女' } const openDetail = (row) => { VxeUI.modal.message({ status: 'success', content: `点击了${row.name}` }) } </script> 转载自https://www.cnblogs.com/qaz666/p/18561550
-
导出 HTML 文件 <template> <div> <vxe-button @click="exportEvent">直接导出 HTML 文件</vxe-button> <vxe-table show-footer ref="tableRef" :export-config="{}" :footer-data="footerData" :data="tableData"> <vxe-column field="seq" type="seq" width="70"></vxe-column> <vxe-colgroup title="分组1"> <vxe-column field="name" title="Name"></vxe-column> </vxe-colgroup> <vxe-colgroup title="分组2"> <vxe-column field="sex" title="Sex"></vxe-column> <vxe-column field="age" title="Age"></vxe-column> </vxe-colgroup> </vxe-table> </div> </template> <script> export default { data () { const tableData = [ { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', age: 28, address: 'test abc' }, { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', age: 22, address: 'Guangzhou' }, { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', age: 32, address: 'Shanghai' }, { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', age: 24, address: 'Shanghai' } ] const footerData = [ { seq: '合计', sex: '666', age: '999' } ] return { tableData, footerData } }, methods: { exportEvent () { const $table = this.$refs.tableRef if ($table) { $table.exportData({ type: 'html' }) } } } } </script> 转载自http://cnblogs.com/qaz666/p/18560845
-
导出时单元格类型默认是自动转换的,如果是需要字符串类型,可以通过 column.cell-type 设置 <template> <div> <vxe-button @click="exportEvent">直接导出 CSV 文件</vxe-button> <vxe-table show-footer ref="tableRef" :export-config="{}" :footer-data="footerData" :data="tableData"> <vxe-column field="seq" type="seq" width="70"></vxe-column> <vxe-column field="name" title="Name"></vxe-column> <vxe-column field="sex" title="Sex"></vxe-column> <vxe-column field="no1" title="NO1"></vxe-column> <vxe-column field="no2" title="NO2" cell-type="string"></vxe-column> </vxe-table> </div> </template> <script> export default { data () { const tableData = [ { id: 10001, name: 'Test1', role: 'Develop', sex: 'Man', no1: '028', no2: '028' }, { id: 10002, name: 'Test2', role: 'Test', sex: 'Women', no1: '220', no2: '220' }, { id: 10003, name: 'Test3', role: 'PM', sex: 'Man', no1: '003200', no2: '003200' }, { id: 10004, name: 'Test4', role: 'Designer', sex: 'Women', no1: '02040', no2: '02040' } ] const footerData = [ { seq: '合计', sex: '666', age: '999' } ] return { tableData, footerData } }, methods: { exportEvent () { const $table = this.$refs.tableRef if ($table) { $table.exportData({ type: 'csv' }) } } } } </script> 转载自https://www.cnblogs.com/qaz666/p/18560839
上滑加载中
推荐直播
-
华为云码道Agent集成与鸿蒙实战2026/08/11 周二 19:00-21:00
王一男-华为云码道产品规划专家;李炎-华为云码道产品专家;彭江敏-华为云鸿蒙端云一体化开发专家
本次直播带你解读华为云码道7月份产品新特性、新功能。更有专家演示码道Agent Space × 钉钉机器集成实战,从0到1打通消息通道;码道鸿蒙端云一体化实战,快速搭建员工签到系统。
回顾中 -
华为云开发者AI素养直播课·第五期2026/09/04 周五 16:00-18:00
林华鼎-华为云AI开发者运营负责人;蒋春阳-华为云AI开发者案例开发专家
本期直播内容: AI工具体验营 · 第5-8课连讲。Agent-Team 多智能体协作完成毕业设计实践
回顾中 -
华为云开发者AI素养ClassRoom·第六期2026/09/08 周二 19:00-20:00
樊渊-2026华为软件挑战赛冠军
高手来了:看软挑高手解析二维排样问题—从工业难题到算法突破
回顾中
热门标签