问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

vue项目开发实战案例(vue项目开发实战案例的介绍)

发布网友 发布时间:2024-09-06 19:59

我来回答

1个回答

热心网友 时间:2024-09-13 09:50

Vue实战(六)通用Table组件

本文是Vue实战系列的第六篇文章,主要介绍Falcon项目中通用Table组件的开发和使用。Falcon项目地址:

随着业务的发展和功能的增多,我们发现不少页面都具备相似的功能,这里举几个比较俗的例子:可以多选的下拉菜单,带输入的对话框,日期选择器等等,于是我们会想办法将这些共有的功能抽取成一个个公共组件,以便能够在不同的页面或业务中使用。

对于一个中后台类的项目,一个比较常见的展示形式就是Table了,相信大家都不陌生,如下图所示:

一个Table通常由如下几个部分构成:

除此之外,由于Table中的数据往往都是从后端获取的,所以这个包含Table的页面还需要发起一个请求,并且将最终的内容渲染在表格之内,请求的过程由于是异步的,所以需要给用户展示一个Loading动画;当请求数据为空时,需要显示一个占位的空元素控件。

在Falcon项目的实践中,我们发现,每一个页面中的Table除了行数,列数,及单元格的内容不同之外,其它的地方,包括样式,分页及数据处理逻辑都是一样的,每次新增一个这样的页面无非就是拷贝粘贴了,那么在这种情况下,我们抽取出了一个通用的Table组件,取名为:TableBox。

说到这里插一个题外话:

关于这个问题我认为,如果一个功能只出现在了一个或两个页面中,往往是没有必要处理的,因为一两个功能的重复还不足以说明问题,也很难看出其中的共性,如果强行抽取的话,反而会增加维护的负担;如果出现的地方超过了两处,那么我们就需要考虑将这个功能进行抽取了,我也常常和Team的人说:“如果一个功能你拷贝粘贴了1次,没关系,不用纠结;2次的话,就得考虑其复用性和组件化了”。

当然,以上内容只适用于那些初期开发过程中无法预测未来变化的项目,如果刚开始产品设计的时候,就能够充分的预见和考虑未来的业务发展,并且给出详细的产品及UI设计方案,那么就另当别论了。

回到我们的主题,抽取这个TableBox其实并不是一气呵成的,而是在业务迭代中,不断地发现新的场景,新的问题,带着这些问题我们不断的优化TableBox,最终达到一个较为完整的状态。这也符合Vue本身渐进式的理念。接下来我们花些时间,一起探讨一下这些场景和问题:

我们发现,对于不同的页面,只要带有Table的,其数据都需要从远端服务器获取,一般情况下,我们会在每个业务中都去写一下这个网络获取数据的逻辑,但是,如果仔细想想,你就会发现,其实这类列表数据获取和处理的逻辑都是一样的。所以针对这个情况,我们只要和后端协商好列表相关的统一API数据结构,如:

那么数据获取,渲染,Loading动画展示隐藏,分页加载等操作都可以在TableBox中完成。

这个组件需要的只是向外暴露出数据请求的API地址及各种参数:

然后写好对应的获取数据的fetchData方法:

这样对于调用者来说,只需要简单的传入相关API地址及参数就可以了,数据加载的事情让TableBox去处理就好了,非常的方便。

因为TableBox组件本身是和业务无关的,所以其肯定无法知道我的这个Table的表头是什么,有多少行,也无法知道每一行展示什么数据,这些内容全部应该由父组件告知TableBox。

要实现以上的功能,我们可以借助于Vue本身提供的强大的工具Slot,如果简单点说,大家可以把Slot理解为一个坑位,因为大多数情况下,组件自己无法预先知道某块区域放置什么内容,那么组件可以先将个区域放置一个Slot,就是挖个坑,当父组件引入子组件时,会告诉子组件往这个坑位中填充什么样的内容。

回到我们的TableBox组件,我们首先挖两个坑(放置两个Slot),命名为ths和item,分别用于表头和行列表内容:

这样对于表头的数据,可以由引入TableBox的父组件来指定,用法如下,其中slot='ths'就是刚才我们在TableBox

中放置的Slot

同样,对于每一行的内容,也是由引入TableBox的父组件来指定,用法如下:

在开发业务的过程中,遇到一个场景:当页面数据已经全部加载完毕后,在某些场景下需要改变Table中某些数据的状态(删除某列或改变某一列的数据)。

这里具体举个Falcon中的实际例子:

我们允许用户给每个项目分配多个环境,以区分测试,生产,开发和各种自定义的场景,在每个环境下,用户可以设置不同的GitBranch。用户点击ChooseBranch按钮后,会触发一个请求到后端,变更当前环境的GitBranch,修改成功后该列表项的按钮会显示为CurrentBranch。

由于以上逻辑都是在引入了TableBox的父组件中完成的,其能够控制数据的刷新,由于场景1中我们已经把数据请求的逻辑都封装在了TableBox中,所以我们需要让其向外暴露出一个Boolean属性:reloadData,当此属性为true时,TableBox会重新请求一次API,并刷新列表。

同理,由于操作数据是由父组件发起的,所父组件中也需要有同样的属性,并且和TableBox中的reloadData保持数据同步,这里用到了Vue2.3版本增加的一个.sync修饰符进行处理。

这样,当reloadData在数据更新完毕后还原为false状态时,我们可以显示的触发一个emit事件:

由于目前所有的数据获取都是在TableBox内部处理的,所以父组件本身是无法直接获取到数据的。但是在某些情况下,我们又希望父组件能够获取到数据,以便能够在顶层进行更灵活的处理,这时我们就需要在TableBox内部将数据抛出。

抛出的方式也很简单,我们可以使用emit方法抛出一个事件。根据这个思路我们改造一下上文提到的fetchData方法:

然后在父组件中监听这个事件,这样就能获取到完整的数据了。

解决了以上4个场景的问题后,我们这个TableBox可以说告一段落了,后续如果有遇到新的场景,新的问题,我们只需要不断的去优化去完善这个组件即可。

到目前为止,TableBox已经应用到了我们内部的三个后台项目约几十个页面中,可以说大大节省了我们的时间,提升了整体效率。

并且随着这样的组件越来越多,甚至我们的后端工程师经过简短的培训,也可以上手部分前端页面的开发了。

最后附上TableBox的地址:

Vue2/ArcGis4开发实战

更新:2021-8-18

最近用Vue2结合ArcGis4做了一个项目,因为此前并没有怎么接触过ArcGisforJavaScript,所以整个过程还是比较痛苦的,虽然GIS官网有例子,并没有起到什么实质作用,网上关于vue/gis的资料又少的可怜,好了废话不多说,直接上干货!

安装好cli后,开始引入GIS,在目录srcassetsjs下新建下新建ArcGisServe.js文件,供我们编写ArcGisServe服务地址。

这里可以定义自己服务器上的底图的地址,默认情况下是官网地址,也可以添加其它服务地址,随意。

这中方法就不多说了,直接script标签引入CDN网址,要说明的是,可用CDN网址较少,官网提供的地址在国内加载较满。

.vue组件

.vue组件

二者都可以通过npm安装的依赖包,不同的是:

vue3+typescript实战记录一

本文记录一些vue3+ts+less开发过程中的一些小问题。

不断开发、不断更新...

新建Hello.vue文件,App.vue文件引入Hello.vue,报错如下:

没有发现模块components/Hello或者它对应的类型申明

参考链接:

要让TypeScript正确推断Vue组件选项中的类型,需要使用defineComponent全局方法定义组件。

参考文档

引用第三方库时,如果第三方类库并没有ts的.d.ts类型的声明文件,则无法在项目中正常使用。如果要顺利使用这些库,就需要我们添加声明文件。

通过此地址可以查找当前安装的库有没有.d.ts的声明文件。

项目中引入echarts

在ts声明查找地址发现echarts已经包含.d.ts类型的声明文件,则不需要我们手动去声明echarts模块

看了基础类型模块,想当然以为定义对象类型为下面示例:

报错如下:

提示不能使用object作为类型。推荐考虑使用Recordstring,unknown代替。

参考文档

参考文档

通过asHTMLElement进行类型转换

在setup中定义的变量和方法,都必须通过return{}暴露出去,外界才能使用,ref函数仅能监听基本类型的变化,不能监听复杂类型的变化(比如对象、数组)

在setup里获取ref绑定的dom,需要在setup的return有ref(null)的属性,模板上ref用对应属性名

通过this.$refs去获取

缺点:在any类型的变量上,访问任何属性都是允许的。它极有可能掩盖了真正的类型错误,所以如果不是非常确定,就不要使用asany。

在src根目录*.d.ts文件中进行类型申明

Vue组件开发有哪些技巧

这次给大家带来Vue组件开发有哪些技巧,Vue组件开发的注意事项有哪些,下面就是实战案例,一起来看一下。

Vue单文件组件开发

当使用vue-cli初始化一个项目的时候,会发现src/components文件夹下有一个HelloWorld.vue文件,这便是单文件组件的基本开发模式。

//注册

Vue.component('my-component',{

template:'pAcustomcomponent!/p'

})

//创建根实例

newVue({

el:'#example'

})

接下来,开始写一个dialog组件。

Dialog

目标对话框组件的基本样式如图:

根据目标样式,可以总结出:

dialog组件需要一个titleprops来标示弹窗标题

dialog组件需要在按下确定按钮时发射出确定事件(即告诉父组件确定了)

同理,dialog组件需要发射出取消事件

dialog组件需要提供一个插槽,便于自定义内容

那么,编码如下:

template

pclass="ta-dialogwrapper"

pclass="ta-dialog"

?pclass="ta-dialogheader"

?span{{title}}/span

?iclass="ios-close-empty"@click="handleCancel()"/i

?/p

?pclass="ta-dialogbody"

?slot/slot

?/p

?pclass="ta-dialogfooter"

?button@click="handleCancel()"取消/button

?button@click="handleOk()"确定/button

?/p

/p

/p

/template

script

exportdefault{

name:'Dialog',

props:{

title:{

?type:String,

?default:'标题'

},

},

methods:{

handleCancel(){

?this.$emit('cancel')

},

handleOk(){

?this.$emit('ok')

},

},

}

/script

这样便完成了dialog组件的开发,使用方法如下:

ta-dialog

title="弹窗标题"

@ok="handleOk"

@cancel="handleCancel"

p我是内容/p

/ta-dialog

这时候发现一个问题,通过使用v-if或者v-show来控制弹窗的展现时,没有动画!!!,看上去很生硬。教练,我想加动画,这时候就该transition组件上场了。使用transition组件结合css能做出很多效果不错的动画。接下来增强dialog组件动画,代码如下:

template

transitionname="slide-down"

pclass="ta-dialogwrapper"v-if="isShow"

?//省略

/p

/transition

/template

script

exportdefault{

data(){

return{

?isShow:true

}

},

methods:{

handleCancel(){

?this.isShow=false

?this.$emit('cancel')

},

handleOk(){

?this.isShow=true

?this.$emit('ok')

},

},

}

/script

可以看到transition组件接收了一个nameprops,那么怎么编写css完成动画呢?很简单的方式,写出两个

关键class(css的className)样式即可:

.slide-down-enter-active{

animation:dialog-enterease.3s;

}

.slide-down-leave-active{

animation:dialog-leaveease.5s;

}

@keyframesdialog-enter{

from{

opacity:0;

transform:translateY(-20px);

}

to{

opacity:1;

transform:translateY(0);

}

}

@keyframesdialog-leave{

from{

opacity:1;

transform:translateY(0);

}

to{

opacity:0;

transform:translateY(-20px);

}

}

就是这么简单就开发出了效果还不错的动效,注意transition组件的name为slide-down,而编写的动画的关键className为slide-down-enter-active和slide-down-leave-active。

封装Dialog做MessageBox

Element的MessageBox的使用方法如下:

this.$confirm('此操作将永久删除该文件,是否继续?','提示',{

confirmButtonText:'确定',

cancelButtonText:'取消',

type:'warning'

}).then(()={

this.$message({

type:'success',

message:'删除成功!'

});

}).catch(()={

this.$message({

type:'info',

message:'已取消删除'

});?

});

看到这段代码,我的感觉就是好神奇好神奇好神奇(惊叹三连)。仔细看看,这个组件其实就是一个封装好的dialog,

接下来,我也要封装一个这样的组件。首先,整理下思路:

Element的使用方法是this.$confirm,这不就是挂到Vue的prototype上就行了

Element的then是确定,catch是取消,promise就可以啦

整理好思路,我就开始编码了:

importVuefrom'vue'

importMessgaeBoxfrom'./src/index'

constCtur=Vue.extend(MessgaeBox)

letinstance=null

constcallback=action={

if(action==='confirm'){

if(instance.showInput){

?instance.resolve({value:instance.inputValue,action})

}else{

?instance.resolve(action)

}

}else{

instance.reject(action)

}

instance=null

}

constshowMessageBox=(tip,title,opts)=newPromise((resolve,reject)={

constpropsData={tip,title,...opts}

instance=newCtur({propsData}).$mount()

instance.reject=reject

instance.resolve=resolve

instance.callback=callback

document.body.appendChild(instance.$el)

})

constconfirm=(tip,title,opts)=showMessageBox(tip,title,opts)

Vue.prototype.$confirm=confirm

至此,可能会疑惑怎么callback呢,其实我编写了一个封装好的dialog并将其命名为MessageBox,

它的代码中,有这样两个方法:

onCancel(){

this.visible=false

this.callback(this.callback.call(this,'cancel'))

},

onConfirm(){

this.visible=false

this.callback(this.callback.call(this,'confirm'))

},

没错,就是确定和取消时进行callback。我还想说一说Vue.extend,代码中引入了MessageBox,

我不是直接newMessageBox而是借助newCtur,因为这样可以定义数据(不仅仅是props),例如:

instance=newCtur({propsData}).$mount()

这时候,页面上其实是还没有MessageBox的,我们需要执行:

document.body.appendChild(instance.$el)

如果你直接这样,你可能会发现MessageBox打开的时候没有动画,而关闭的时候有动画。解决方法也很简单,

appendChild的时候让其仍是不可见,然后使用类这样的代码:

Vue.nextTick(()=instance.visible=true)

这样就有动画了。

总结

通过transition和css实现不错的动画。其中,transition组件的name决定了编写css的两个关键类名为[name]-enter-active和[name]-leave-active

通过Vue.extend继承一个组件的构造函数(不知道怎么说合适,就先这样说),然后通过这个构造函数,便可以实现组件相关属性的自定义(使用场景:js调用组件)

js调用组件时,为了维持组件的动画效果可以先document.body.appendChild然后Vue.nextTick(()=instance.visible=true)

vue实战(7):完整开发登录页面(一)

vue实战(1):准备与资料整理

vue实战(2):初始化项目、搭建底部导航路由

vue实战(3):底部导航显示、搭建各模块静态页面、添加登录页页面与路由

vue实战(4):postman测试数据、封装ajax、使用vuex管理状态

vue实战(5):总结一

vue实战(6):异步显示数据、开发Star组件

vue实战(7):完整开发登录页面(一)

vue实战(8):完整开发登录页面(二)

vue实战(9):总结二

vue实战(10):开发店铺详情(一)

vue实战(11):开发店铺详情(二)

vue实战(12):完结+附学习视频

这一部分内容,回到之前完成的Login.vue页面,做逻辑之前先完成一些必要的效果。

2)判断是否可以发送验证码

3)login.vue页调用并判断

声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
女生多大后可以不在长身高? 如何不用软件把手机投屏到电脑上手机屏幕怎样投放到电脑上 战时拒绝、故意延误军事订货罪既遂的处罚? 战时故意延误军事订货罪处罚标准 名师1+1导读方案:汤姆·索亚历险记目录 三星sm-g7200打开微信慢,无法正常收看,网速不慢。 笔记本电脑如何调亮屏幕亮度 大伙说说洗衣机要不要带烘干好 热烘干洗衣机怎么样 ef英语哪个好 糖粥来源 销售挂面适用什么税率 手机突然不能录音了 vmware虚拟机ip地址怎么设置,在哪里设置? Uibot机器人是什么呀_UI机器人 浏览器javascript怎么开启(浏览器的javascript怎么打开) 在钉钉上请假怎么请? 如何在Win10中恢复被隐藏的U盘文件夹? 到澳大利亚入境时,双氧奶、漂粉能带过去吗?谢谢! 南京特产购物去哪里比较好? 在家怎么快速剪头发视频在家怎么快速剪头发 韩国拍的福宝电影定档什么时候上映 怎么查看历史天气记录? b站的视频可以搬运吗,收益是多少? 我有好多第弟妹妹父亲跟着别人的老婆跑来怎么能为弟弟妹妹讨到父亲生... 为维护家庭荣誉 我勾引老爸的情妇 苹果手机apple music怎么样 excel表格中怎样只删除指定的行数据呢? excel怎么删除指定行? ps一般多久可以学会ps一般多久可以学会画画 vue3.0使用vuex? vue引入组件(vue引入组件的方式有几种) 有哪些设计感强的面包鞋推荐? 怎么彻底删除Edge浏览器呢? 你好,误删除电脑管家文件后无法再安装,提示已安装最新版本,但电脑里... 微信被骗900元怎么追回 公积金贷款利率历年一览表 公积金贷款利率往年利率表 门口狮子摆放有什么讲究 怎么查红安二小老师的电话 湖北黄冈红安二小六年级毕业成绩2016 红安考驾照哪家驾校比较靠谱? 红安县二小2014年六年级考试分数怎么样 红安二小四年级升级考试分数查询 红安县二小2016小考成绩查询黄双,黄满所考得分多少?谢谢! 红安二小小升初在那所中学上学 有什么类似元气骑士的双人闯关游戏? 元气骑士黑暗大骑士剑怎么玩_黑暗大骑士剑实战解析攻略 孕妇能吃韭菜花吗 孕妇吃韭菜花要注意什么 北京天文馆本馆概况