宝哥软件园

加快Vue项目发展的方法

编辑:宝哥软件园 来源:互联网 时间:2021-08-28

现在的发展,比如内部管理平台,大多是匆匆忙忙的。实际上,使用webpack vue开发已经大大提高了效率。但是对于我们的发展水平来说。还有很多地方可以再次提高我们的项目开发效率,让我们更加专注于我们的业务。毕竟,时间就是生命。我们一个一个来讨论。

网络包的巧妙运用

Webpack是我们前端项目工程的基础,但实际上,它远比这个有用。我们可以通过Webpack帮助我们做一些自动化的事情。首先,我们需要了解API require.context()

require.context()

您可以使用require.context()函数创建自己的上下文。它允许您传入要搜索的目录、指示是否应该搜索子目录的标志以及匹配文件的正则表达式。实际上,Webpack通过解析require()的调用来提取以下信息:

目录:/template正则表达式:/。* .然后创建我们自己的上下文。你的意思是,我们可以过滤出我们需要的文件,并通过这种方法读取它们

让我们简单看一下使用:

/* * * id的三个属性的resolve()方法返回解析请求后获得的模块id键()。它返回一个数组,该数组由满足上下文的模块处理的所有请求组成。Id是包含在上下文模块中的模块id。当您使用module . hot . accept */require . context(' demo ',use子目录=false,regexp=/)时,可能会用到它。js $/)//(已创建)。它包含了演示文件夹下的所有文件名(不包括子目录),并带有` js不要混淆,让我们讨论如何在项目中使用它。

组织路由

大家都很熟悉Vue中的路由,类似于声明性配置文件,但实际上非常简洁。现在让我们让他更简洁

分割路线

首先,为了方便我们的管理,我们将路由器目录中的文件分为以下结构

Router //路由文件夹|__index.js //路由组织器:用于初始化路由等。|__common.js //通用路由:声明通用路由|__modules //业务逻辑模块:所有业务逻辑模块|__index.js //自动处理文件:自动引入路由的核心文件| __home.js //业务模块home:business module | _ _ a . js//business module处理amodules文件夹中的业务模块

我们所有的业务逻辑模块都存储在modules文件夹中。至于如何划分业务逻辑模块,相信每个人自然都有自己的一套标准。我们通过上面提到的require.context()编写自动化的核心部分index.js。

const files=require.context(' . ',true,/。js $/)console . log(files . keys())//['。/home.js']返回一个数组让config routers=[] files.keys()。foreach (key={if (key===')。/index . js’)返回配置路由器=配置路由器。文件(密钥)。default)//读取文件中的默认模块})导出默认configRouters //抛出Vue-router所期望的结构中的一个阵列自动化部分。如何编写业务组件部分?甚至更简单

从“@/view/frame/frame”导入框架从“@/view/index/index”导入主页导出默认[//第一页{path: '/index ',名称: '第一页',重定向: '/index ',组件:框架,子组件:[//嵌套路由{ path 3360 ' ',组件: home}]}]常用路由处理

我们项目有很多公共路线需要处理,比如404 A,503 A等等。我们都处理它们

导出默认[//默认页面{path:'/',redirect:'/index ',hidden: true},//未授权页面{path:'/nopermission ',名称:' nopermission ',组件: ()=导入(' @/view/no permission ')},//404 {path:' * ',名称:' lost ',组件: ()=导入(@/view/4000)

这是我们初始化项目路由的最后一步

从“vue”导入vue路由器从“vue-router”导入路由器配置。/modules//import业务逻辑模块从“”导入通用路由器。/common'//介绍通用模块vue.use (vuerouter)导出默认新vuerouter ({mode:' history ',//服务器需要支持scrolbehavior :()=({ y : 0 })。Routes: routerconfig。concat(普通路由器)})估计有些朋友的代码写着不知道这哪里做得好。让我们描述一个场景,比如根据这个结构划分模块。通常,当我们创建home.js时,我们需要手动将这个模块导入到路由文件中声明的位置以供使用。但是,有了上面的index.js,您只需要创建一个home.js,并在使用它时抛出一个符合VueRouter规范的数组,其余的将被忽略。从“”导入路由器配置。/modules//已经为您处理了业务逻辑模块。此外,如果您扩展它,您也可以将钩子作为一个单独的文件取出。

全球组件的统一声明

同理,有了上面的经验,我们就按照葫芦画来处理我们的全局组件。没什么好说的,直接去核心代码

组织结构

组件//组件文件夹|__xxx.vue //其他组件| _ _全局//全局组件文件夹|__index.js //自动化处理文件|__demo.vue //全局演示组件全局处理

从“Vue”let上下文=require.context('导入Vue。false,/。vue $/) contexts.keys()。foreach(组件={let componententity=contexts(组件))。默认//具有内置组件名称vue.component(component entity . name,componententity)})的全局组件注册使用和描述

这个使用起来简单多了,直接在app.js中引用这个文件就可以了

注意:我看到有人用组件名来区分全局组件和普通组件,然后通过正则化来判断是否需要全局注册。我把全局组件直接放在全局文件夹下,然后组件的注册名直接用component.name至于用哪个方法,就看个人了。

充分利用NodeJS

把一个东西保持得和node一样好是一种浪费,让我们看看node能为我们的效率做出什么贡献。

有这样一个场景,我们每次创建一个模块,都要创建一个新的vue文件和对应的路由器配置,而且大部分新页面都是相似的,所以我们要复制粘贴其他页面。想想有点低。现在我们有了node,可以通过node做这个乱七八糟的事情吗?让我们展示我们的想法。

我们主要依靠文件系统和节点的进程来实现这个功能。如果感兴趣,可以深入研究。

首先,我们需要编写我们的节点脚本。这里有一个相对简单的版本。没有什么可验证的文件夹或文件,只是为了实现我们的想法:

/* *快速添加新模块脚本*/const path=require(' path ')const fs=require(' fs ')const粉笔=require('粉笔)const reslove=file=路径。解析(_ dirname’)./src ',文件)//Symbol const const RouterSymbol=Symbol(' router '),viewsymbol=Symbol(' view ')//根路径const rootPath={[Routersymbol]: reslove('路由器/模块'),[viewsymmbol]: reslove('视图')}//loggs const error log=error=console。日志(粉笔。red(`$ { error } `))const DefaultLog=log=console。日志(粉笔。绿色(` ${log.导出默认值[ { path: '/${module} ',名称: ' ',redirect: '/${module} ',component: ()=导入(' @/视图/框架/框架'),子项: [ { path: ' ',完整路径: ' ',名称: ' ',组件: ()=导入(@/view/$ { module }/index ' })]`)/* * *生成文件* @param {*}==' '!等待fs。existssync(dirPath)){ await fs。mkdirsync(dirPath)默认日志(` created $ { dirPath } `)} if(!等待fs。existssync(文件路径)){//创建文件wait fs.openSync(filePath,' w ')默认日志(` created $ { file path } `)} wait fs。writelefilesync(文件路径,内容,' utf8 ')catch(错误){ errorLog(错误)} } //模块-方法映射常数生成=新映射([ [视图],异步(模块)={ //模块文件常量文件路径=路径。join(rootPath[viewsymbol],module)const vuePath=path。连接(文件路径,请输入模块名称(英文):`)//file const files=[' view ',' router'] //和命令行进行交互获取的创建的模块名称process.stdin.on('data ',(chunk)={ try { if(!moduleName){ moduleName=chunk } else { chunk=chunk。切片(0,-2) //删除/n DefaultLog(` 0新模块名为${chunk} `)文件。forEach(异步(el,index)={ //执行创建语句等待几代人。get(`$ { El } `).调用(空,大块。tostring())if(index===文件。长度-1){过程。stdin。emit(' end ')})} } catch(错误日志(error)} })进程。stdin。on(' end ',()={默认日志('创建模块成功')})下面我们看使用的流程

这样我们就分别创建了某视频剪辑软件和路由器的文件,而且已经注入了内容。按照我们提前声明的组件

注意:这只是一个简单的思路,通过结节强大的文件处理能力,我们能做的事情远不止这些。

发挥混入类的威力

某视频剪辑软件中的混入混入类是一种提供分发某视频剪辑软件组件中可复用功能的非常灵活的方式。听说在3.0版本中可能会用钩住的形式实现,但这并不妨碍它的强大。基础部分的可以看这里。这里主要来讨论混入类能在什么情景下帮助我们。

比如我们的大量的表格页面,仔细一扒拉你发现非常多的东西都是可以复用的例如分页,表格高度,加载方法,老丁声明等一大堆的东西。下面我们来整理出来一个简单的list.vue

Const list={data () {return {//这些东西都是在列表中处理的,所以不需要在每一页都手动这么做。Loading: false,//页码: 1并伴有加载状态,//页码Pagesize 3360 15,//页面长度totalCount: 0,//总页数Page size 3360[15,20,25,30],//页面长度pagelayout:' total,size,prev,pager,next,jumper ',//页面布局列表: []},methods 3360 {//分页返回事件handlesizechange (valpagesize=val//todo},handlecurrentchange (val) {this。pageno=val//todo},/* * *表数据请求的回调成功处理了公共部分(分页,加载被取消后),将控制权交给页* @ param {*} apiresult * @返回{ * } promise */listssuccb(API result={ }){返回新的promise ((reslove,Reject)={让tempList=[] //临时listtry {this。loading=false//todo//throw reslove(templist)} catch(error){ reject(error)}),/* * *处理异常情况*==简单的处理就是清空表并取消加载*/listeexceptioncb(error){ this。加载=假控制台。错误(error)}},Created() {//此生命周期是在使用组件的生命周期之前。这个。$ nexttick()。然后(()={//todo})}}导出默认列表我们直接在组件中使用这个混合。

从“@/mixin/list”/导入mixin { getlist }从“@/API/demo”导出默认{ name : ' mixin-demo ',mixin :[mixin],//使用mixin data(){ return } },methods : {//load list load(){ const para={ } this。loading=true getlist(段)。然后((结果)={this。listsuccesscb(结果)。然后((list)={this。list=list})。catch ((err)={console。log (err)})})。catch ((err)={this。listexception CB (err)})}},created () {this。load()} }/脚本使用

注意:font color='red'mixins,很简单,但是注释和引用一定要做好,不然新成员入队的时候很可能会看起来很傻,不利于后期维护。这也是一把双刃剑。此外:必须谨慎使用全局混合。如果没有必要,我还是不建议使用。/font

该组件被进一步封装

众所周知,组件化的最大优势是它的高重用性和灵活性。但是,如何包装组件,包装到什么程度才更方便我们。没有标准答案。我们只按照高内聚、低耦合的指导思想封装我们的业务公共组件,这使得我们的业务页面结构更加简单,加快了我们的开发效率。如果你封装的再多一点,页面可能会变成这样:

模板框-内容!-header title part-page-title bread slot=' title ' : combs='[{ name 3360 ' xx management ',path: ' ',active3360 true,icon:''},{name:' xxxx ',path: ' ',active 3360 true,icon : ' ' }]'/bread/page-title!-table part-div base-table v-loading=' loading ' : columns=' headers ' : list=' list ' : page-no=' page no ' : page-size=' page size ' : total-count=' total count ' @ delete im ' @ change-size=' handlesizechange ' @ change-page=' handlecurrentchange '/base-table/div/box-content/template,一目了然。

无状态组件

无状态的HTML组件,比如去掉页眉和菜单后的内容部分,最容易激起我们封装的欲望。没有什么需要复杂的交互,但是我们必须写好每一页。你说你不会打开它。谁会打开它

模板div class=' container-fluid ' : class='[content class]' El-row El-col : span=' 24 '!-带# fff BG-div class=' box ' div class=' box-body '插槽/插槽/div/div/El-col/El-row/div/模板的盒子上面这个处理非常的简单,但是你在项目中会非常频繁的使用过到,那么这个封装就很有必要了。

ElementUI表组件封装

ElementUI中得组件其实已经封装得很优秀了,但是表格使用得时候还是有一堆得代码在我看来是不需要在业务中重复写得。封装到靠配置来进行表格得书写得一步我觉得就差不多了,下面是一个小演示

模板El-row El-col : span=' 24 ' El-table : data=' list '边框大小=' mini ' @ selection-change=' handleSelectionChange ' : max-height=' table height ' v-bind=' $ attrs '!- -模板v-for='(列,索引)在列'插槽名称='前端插槽'/插槽!-序号-El-table-column :键=' index ' v-if='列。type==' selection ' ' type=' selection ' width=' 55 '/El-table-column!-复选框-El-table-column :键=' index ' v-else-if='列。type==' index ' ' type=' index ' width=' 50 ' label='序号/El-表-列!-具体内容-El-table-column : key=' index ' v-else align=' left ' : label=' column。title ' : width='列。'宽度'模板slot-scope='scope '!-仅仅显示文字-标签v-if='!列。隐藏!-如果隐藏的为真实的的时候那么当前格可以不显示,可以选择显示自定义的吃角子老虎。-操作按钮-标签v-if='列。type==' operate ' ' a href=' JavaScript : void(0)' rel=' external nofollow ' rel=' external nofollow ' class=' operation-button ' v-for='(operation,index)在列中。operations ' : key=' index ' @ click=' handleClick(operate,scope。row)' { { operate。name } }/label span v-else { { scope。行[列。key]}/span/label!-使用狭槽的情况下-标签v-if='column.slot '!-具名插槽-插槽v-if='列。插槽“:名称=”列。插槽' :作用域='作用域'/插槽/标签/模板/El-表-列/模板!-默认的slot-slot//El-table/El-col/El-row/模板导出默认值{ name : ' base-table ',prop : {//核心数据list: { type: Array,default: ()=[] },columns: { type: Array,required: true,default: ()=[] },data(){ return { table height : XXX } },methods 3360 {//处理点击事件手柄点击(动作,数据){ //发出事件这个$emit(`${action.emitKey} `,data) } }}使用:

基表v-loading=' loading ' :列=' headers ' : list=' list ' @ view=' viewCb '!-自定义的slot-template slot=' demo slot ' slot-scope=' { scope } ' span { { scope。row } }/span/模板!-默认的狭槽如果交互很复杂我们还可以直接使用表格内部的组件埃尔表列标签='操作宽度='200 '模板slot-scope=' scope ' a href=' JavaScript : void(0)' rel=' external nofollow ' rel=' external nofollow ' @ click=' default slot(scope。row)' XXX/a/template/El-table-column/base-tableexport默认{ name : ' table-demo ',data () { return { //表格头部配置标题RS :[{键: ' XXX ',标题: '测试},{ title: 'xxx ',hidden: true,slot: 'demoslot'},{ title: '操作,类型:"操作",操作:[{ name : }详情,emitKey: 'view'} ] } ] } },methods: { viewCb(){ //todo },defaultSlot(){ //todo } }}这样封装过的表格,应付基本的一些需求问题应该不大。至于特殊的要求可以一步一步的进行完善。

总结

这些东西不是语法糖果,却能真正加快我们在项目中的效率。让我们自己乃至整个团队摆脱复杂的复制粘贴。至于速度和质量。我认为使用通用组件的质量可控性会更高。我建议公共笔记一定要写得全面详细,这样可以大大降低我们的沟通成本。至于组件的包装,就看你的业务了。

以上观点纯属个人观点。如有错误,谢谢指正。

示例代码仍在整理中。

以上就是本文的全部内容。希望对大家的学习有帮助,支持我们。

更多资讯
游戏推荐
更多+