1.在vue中循环获取对象中的属性名和属性值
<ul> <li v-for="(value,key,index) in obj" :key="index"></li> </ul> <!--其中value是属性值,key是对应的属性名-->
2.在前一页面通过this.$router.push({name:"nextPage"})跳转的时候,需要将当前页面的一个数组带往下一个页面。
解决方案有两种,一种是路由传参,一种是查询字符串传参
路由传参:
//前页面 this.$router.push({name:"nextPage",params:{arr:this.arr}}) //后页面,不需要修改router.js中参数 created(){ let arr=this.$route.params.arr console.log(arr) }
查询字符串传参
//前页面 this.$router.push({name:"nextPage",query:{arr:this.arr}}) //后页面 created(){ let arr=this.$route.query.arr console.log(arr) }
比较:路由传参和查询字符串传参都可以在跳转后的页面拿到数据(数据仍然是数组格式),但是,路由传参方式会将原本后面页面的路径地址改成去掉所有path累加的原始路径;而查询字符串传参会将数组作为字符串添加到路由后面。
3.在使用element-ui开发时,对于文件上传和下载的方法
1)文件下载
后端:有两个接口,一个用来获取文件的名称,一个是下载地址,具体如下
//API文件。⬇️ //可以在API文件中管理一些后台路径 Let common={ Download:’后台下载地址’ } export default{common} //后台接口调用思路是:先获取下载的文件名称,通过后台下载的地址+文件名获取文件 //接口调用函数 Export function getfilename(){ Return request({ URL:’获取文件名称的接口地址’, Method:’Get’ }) }
前端:引入API中用到的方法和路径,在方法中:
引入API中方法与路径 import {common,getfilename} from ‘@/api/mg.js’ importfile(){ Getfilename().then(res=>{ //获取下载的文件名称 Let filename=res.data.filename //下载文件 Window.location.href=`${common.dowmload}?filename=${Filename}` }) }
这样便可以下载到来自服务器的文件~,后来发现公司自己封装的下载的函数在main.js中,在使用时,直接在获取文件名的请求后写
this.download(filename)这样就可以直接下载了
2) 文件上传
文件上传比较复杂,使用到了来自element-ui中的el-upload 组件,但是对于其使用我不太熟练,先记录下我们实现的过程吧。
文件上传是post请求;
<el-upload Style=“Display:inline-block” Action=“” Multiple :File-list=“Filelist” > <!—多文件上传—> <el-button @click=“Importfiles”><i class=“El-icon-upload”></i>上传文件</el-button> </el-upload>
在data中:
Data(){ Return{ Filelist:[] } }
重点是,上传的方法:
Importfiles(item){ //这里需要2个参数,一个是文件名称,一个是文件 Let form=new FormData()//之后补充一下这是个什么
form.append('file',item.file)
form.append('filename',item.filename)
//调用API接口函数 uploadfile,同样需要上传文件的地址
uploadfile(form).then(res=>{
//流程是这样,这里就可以读取到上传文件是否成功的状态了,然后可以进行判断与操作
}) }
前端大神看到的这里的解决方案路径是:文件的上传与下载
4.在父组件触发子组件中的方法
之前有很多在子组件中触发父组件传递给子组件的事件,用$emit,这种使用在如果父组件传递给子组件需要在函数中用到的值不多的时候使用会比较好,子组件自成一体,可以解决内部自己的操作。但是在子组件很多这个函数用到的数据需要来自父组件的时候,使用ref直接将存放在父组件中的值取用到子组件,并触发事件就好了。
//父组件中: <child ref="child"></child> data(){ return{ applyId:’’, list:[], isShow:false } }
mounted(){
//触发子组件中存放的事件,但是其中用到的参数是来自父组件的
this.$refs.child.getData({no:this.applyId,list:this.list,isShow:this.isShow})
}
子组件中只放函数就可以了
//子组件中
import {getDetail} from "@/api/index.js"
data(){ return{ no:’’, list:[], isShow:false } } methods:{ getData(no,list,isShow){ //拿到父组件中传进来的参数,赋值给子组件中的数据存放在data,而不是通过props获取
this.no=no
this.list=list this.isShow=isShow
let json={
no,list,isShow
}
getDetail(json).then(res=>{
console.log(res.data)
}) } }
5.this.$set的用法
问题描述:在项目中,将获取到的参数分别赋值给data中的对象作为属性与值,奇怪的是在控制台中可以打印出来,但是在页面对应位置却始终拿不到这个值,也不能当作数据在其中使用,$set就是解决这样问题的方案,将其中获取到的值作为属性值赋予对象
data(){ return{ detail:{} } } mounted(){ getDetail().then(res=>{ //发送一个异步请求 let data=res.data this.$set(this.detail,’title’,data.title) //这样就可以将属性与值强行赋予detail了,其中参数为this.$set(对象,属性,值) }) }
6.使用computed和watch检测element-ui中table多选变化
在使用element-ui中的表哥组件时,使用@selectionChange="handleChange" ,handleChange(val){val就是拿到的选中项信息},可以收集表哥中选中的条目,但是这个操作只能触发一次,如果要实时监听变化的话,可以使用computed+watch达到vuex的效果
<el-table multiple @selectionChange=“handleChange” > </el-table> data(){ return{ selctions:[] } } computed:{ chosen(){ return this.selections } }, watch:{ chosen(newVal,oldVal){ //这样就可以实时监控选中项的变化了,而不是 this.selections=newVal
this.list=[...new Set(this.list)] } }, methods:{ handleChange(val){ //多选表中选中项的收集 this.selections=val
for(var i=0;i<val.length;i++){
this.list.push(var[i].id)//收集id属性值
} } }
last but important:
在项目中,在同时用到的数据中 有一个list数组是用来存储选中项信息中的某一项属性,并将其传递给后续的页面作为请求参数。
这时,使用computed和watch监控的只是选中项,作为循环被存放在list中的内容就出现了重复,这时需要在watch时同时对list去重
7.在使用element-ui时,对于多选框中项目的选中状态进行记录(分页)
问题:在使用el-table和pagination将数据进行分页,切换页面时,会取消之前页面项目的选中状态
在html中,需要在el-table做限制,在多选的行(type="selection")中添加reserve-selection---在数据更新之后,保留之前选中的数据;
在el-table中加入:row-key对每行进行标识,rowKey是一个函数
<el-table ref="multipleTable :row-key="rowKey"> <el-table-column type="selection" reserve-selection/> <el-table-column label="序号"> <template scope="scope"> <span>{{scope.$index+(pagination.page-1)*pagination.limit+1}}</span>
<!--scope.$index 是针对分页时对其中的项目从1开始排序改变成解除分页后递增的顺序--> </template> </el-table-column> </el-table>
rowKey(row){ return row.applyNo }
//这里的applyNo是可以作为唯一确定改行数据的标记
8.keep-alive
keep-alive包裹组件后,期间的内容可以选择不重新加载
activated和deactivated钩子是加了keep-alive之后有效的函数,钩子执行顺序是:created--mounted--activated,在退出时触发deactivated;
其中mounted只在第一次进去页面时执行一次,activated中的函数每次进入组件都会执行
9.前后端参数是数组的交互
由页面A获取到数组作为将要跳转去到的页面B的查询参数:
this.$router.push({name:"Next",query:{list:this.list}}),这时查询字符串将数组分割成单个的值作为list存放在query里面,在页面B中首次获取到的list也确实是数组格式:this.$route.query.list。
但是,再次刷新页面B的时候,可以在请求头中发现,这时的list已经变成字符串格式了!
这样,在页面B及其子组件中需要使用到作为数组的list时,发送的请求就会出现问题。那么怎么使list在页面A和B之间传递的时候变成数组格式呢?--可以转成json字符串
页面A------:this.$router.push({name:"next",query:{list:JSON.stringify(this.list)}})
页面B------:tlet list=this.$route.query.list; JSON.parse(list)
在页面B中,list也成为数组啦~~
10.在一个页面中同时有4个选项卡,分别调用不同接口获取数据填入表格,这是个3级页面,在关闭这个页面的时候发送了很严重的问题:我写的请求方法都被调用了,没有请求的时候也调用!!!!!
后来发现是因为我在data中直接获取路由参数并对其中的数据进行了赋值:
其中一个选项卡:
export default{ data(){ return{ no:this.$route.params.applyNo, applyType:this.$route.params.applyType } } }
//在created或者mounted中调用方法渲染数据都会有这种现象
错误是“申请单号不能为空”,后来在发送请求前判断一下申请单号是否存在,存在的时候再发请求,就可以避免这个报错了。但是,在规范上还是将data赋值写在调用方法的时候比较好。
11.返回之前页面
项目中有需求:'返回'按钮点击,返回到进入该页面B的之前的页面A,由于使用的是后台生成的动态路由,我们前端处理这个操作的时候不能使用this.$router.go(-1)或者window.history.back(-1),要返回的必须是进入这个页面既定的路由地址,不使用localstorage、vuex、router的话,确实是有点难的。
因为是3个模块公用一个轨迹页面(B页面),在每个页面中的路由name不同,甚至页面A的路由参数都不同,这就很难办了。后来,比较了下这其中的差异,将所有前一个页面的参数去同存异,都传递给轨迹页面B,在router.js中各个模块拷贝轨迹的路由地址,分别带有不同的参数,但不要改变name(name不变的话,其实控制台会报warning,不过这不重要)我们采用的是路由传参
router.js :这里省略了一些代码 { path:’/newService’, component:()=>{import(文件地址)}, meta:{title:’new service’}, children:[ { path:’detail/:appluNo’, name:’newServiceDetail’, component:()=>{import(详情文件地址)}, }, { path:’detail/:applyNo/:applyType’, name:’newServiceDetail’, component:()=>{import(这是可以与详情用同一个页面,只是参数不同,在页面中会有判断文件地址)} }, //以上2个路径是进入轨迹页面的地址,分别带有不同的参数 { path:’newServicetrack/:applyNo’, name:’Track’, componnet:()=>{import(轨迹文件地址)} }, { path:’track/:applyNo/:applyType’, name:’newServiceTrack’, component:()=>{import(与上面的轨迹页面地址相同)} } ] }
需要注意的是,在同一个页面中需要获取的参数不同,可以将不同参数的路由地址拿出来再做一个路由,这样不同的参数个数可以拿到各自进入共同页面的方法。
言归正传,在详情页面跳入轨迹页面,其实详情页面的路由name是一致的,即使是3个模块公用的轨迹页面,也能依据区分开(给轨迹页面加各自特别的前缀newService当前模块的tag+Detail/track)
这样,在轨迹页面代码可以写:
返回按钮的方法名为backPage methods:{ backPage(){ let main=‘’ //用来接收三个模块各自除参数外的地址 let added=‘’ // 用来接收参数 let name=this.$route.name //获取当前轨迹页面属于哪个模块 switch (name) { case ‘newServicetrack’: main=`/newService/newServiceDetail/${this.$route.params.applyNo}` //详情页面公共部分 break; case ‘另一个模块中轨迹路由的name’: main=‘进入另一个模块的前一个页面公用地址’ break; default: main=‘第三个模块轨迹路由名称’ break; } if(this.$route.params.applyType){ added=`/${this.$route.params.applyType}` }else{ added=‘’ } } let path=main+added this.$router.push(`${path}`)
//注意使用模板字符串 }
简而言之,就是进入轨迹页面的参数需要根据需求增减,,然后拼接出上级页面的地址,除此之外我没有想到比较好的方法,若有更高明的方法,欢迎留言交流~
12.element-ui中table分页后的选中项状态保留
在element-ui中使用pagination进行分页
使用pagination的分页代码 <pagination :total="pagination.total" :page.sync="pagination.page" :limit.sync="pagination.limit" @pagination="handlePage"> data(){ return{ pagination:{ total:0,//数据总量 page:1,//当前页码 limit:10//每页显示条数 } } }
el-table中
<el-table reg="multipleTable" :row-key="rowKey" :data="tableData"> <el-table-column type="selection" resevse-selection/>
<!--在多选项里面添加reserve-selection可以记住选中状态--> <el-table-column></el-table-column> </el-table>
export defaul{
methods:{
rowKey(row){
return row.id
//row.id作为可以唯一标记当前行的在行内的字段
}
}
}
13.element-ui中表格取消选中状态
在项目中经常会有返回和前进的操作,进入某个可以公用的页面我们可以通过判断在地址中接收到的前一页面传递的参数值来控制操作。当中间的页面是有表格的,返回--再次进入该页面是不需要缓存表格之前选中状态的,而回退到这个页面的时候,需要缓存选中状态(我说的是在使用keep-alive对整个项目根据name来缓存的状态,当然可以根据其他形式决定是否缓存当前页面的数据),这时候需要清除table的选中状态
<el-table ref="multipleTable"> <el-table-column type="selection"></el-table-column> </el-table> 取消选中的函数: methods:{ clear(){ this.$refs.multipleTable.clearSelection() } }
14.双向绑定中对于输入框中数据进行处理
输入框有时候在复制粘贴到输入框成为其内容的时候,需要去除空格,这里可以将绑定的数据进行操作:
<el-input v-model.trim="form.name" />
对v-model使用.trim就可以避免数据中带有空格带来的影响了!
同样的,对输入其中的数据限制为数据类型可以加.number,但是number通过parseFloat处理数据,输入‘abc4343’这样的数据也不会报错,要谨慎使用
15.再element-ui中清除查询条件form表单
项目中有keep-alive机制“统治”,有一些可能根据条件确定是否缓存的也不能实际跳过缓存的桎梏,这时候根据进入页面的某一个地址参数值不同手动清除查询条件啦,这是真的烦!网上有很多方法但都有点支离破碎不全面,好在找到了以最小的变动实现表单清除的效果,话不多说,上代码
<el-form ref="form" :model="form"> <el-form-item label="部门" prop="dept"> <el-select v-model="form.dept"> <el-option v-for="item in depts" :label="item.value" :key="item.key" :value="item.value"></el-option> </el-select> </el-form-item> <el-form-item label="城市" prop="city"> <el-select v-model="form.city"> <el-option v-for="item in cities" :label="item.value" :key="item.key" :value="item.value"></el-option> </el-select> </el-form-item> </el-form> <el-button size="mini" @click="reset"><i class="el-icon-refresh-left"></i>重置</el-button>
js代码如下: <script> export default{ data(){ return{ depts:[ {key:0,value:'运营部'}, {key:1,value:'开发部'} ], cities:[ {key:0,value:'北京'}, {key:1,value:'广州'}, {key:2,value:'上海'}, {key:3,value:'重庆'} ], form:{ city:'', dept:'' } } }, methods:{ reset(){ this.$refs.form.resetFields() } } } </script>
简而言之,就是为
1) el-form声明ref,并用:model绑定表单中的数据对象form;
2) 为每个el-form-item声明 prop并指向当前数据项在form中对应的属性
3) 执行清楚表单项的方法是 this.$refs.form.resetFields() 其中 form指的是ref声明的对于当前表单的称谓
写在最后:感谢有经验的同事处理问题,我只是将他们的操作整理出来!小白爬坡,任重道远