vue官方地址: https://cn.vuejs.org/v2/api/#Vue-set
1:前台校验 不需要使用req,直接在校验规则中 用true 和false 在校验.
否则就会造成校验两次的.
2: <el-form : 上设置abel-width 表单域标签的宽度,作为 Form 直接子元素的 form-item 会继承该值.
<el-form :model="actualBeneficiary" label-width="100px" :rules="rules" ref="actualBeneficiary">
3: 设置按钮默认样式
按钮:
<template slot-scope="scope">
<el-button size="small" class="default" :class="{ active:indexClass == scope.$index }"
@click="defaultLinkman(scope.$index, scope.row)">设为默认经办人
</el-button>
</template>
事件:
defaultLinkman(index, row) {
//设置默认经办人标识位
row.defaultLinkMainInfo = '1';
this.$notify({
title: '默认经办人设置成功',
message: '',
type: 'success'
});
this.indexClass = index;
},
样式:
.default {
color: #404040;
background: #f8f8f8;
}
.active {
color: #fff;
background: #0066cc;
}
4: 数组删除:
按钮:
<template slot-scope="scope">
<el-button size="small" @click="deleteLinkman(scope.$index, scope.row)">删除</el-button>
</template>
事件:
deleteLinkman(index, row) {
this.custLinkMainInfoList.splice(index, 1);
},
splice方法:
splice(index,len,[item])它也可以用来替换/删除/添加数组内某一个或者几个值(该方法会改变原始数组)
index:数组开始下标
len: 替换/删除的长度
item:替换的值,删除操作的话 item为空
5:校验:
校验的是 ref的名字要和 $resf 一样. 然后在写事件的是传入参对象的时候要记得加 '' 不然校验不了
代码按钮:
<el-button type="primary" @click="saveActualBeneficiary('actualBeneficiary')">确 定</el-button>
方法:
saveActualBeneficiary(actualBeneficiary) {
console.log(this.$refs[actualBeneficiary]);
this.$refs[actualBeneficiary].validate((valid) => {
if (valid) {
if (this.saveOrUpdateFlag === 0) {
//新增
this.actualBeneficiarys.push(this.actualBeneficiary);
} else {
//修改
}
this.actualDialogFormVisible = false;
} else {
return false;
}
});
},
如果是时间类型的话,要把rules的校验规则改为string类型的不然校验通不过.
错误样式:
Error in event handler for "el.form.change": "TypeError: dateObject.getTime is not a function"
vue.esm.js?efeb:1687 TypeError: dateObject.getTime is not a function
原因可能是:elementUI自带的格式转换后会将绑定值转为字符串,而校验规则中的【type: 'date'】已经不匹配,至于它的报错是因为转换为字符串,不是date对象所以没有getTime这个方法了。
6:vue实现对表格数据的增删改查
重点修改:
当我们想要修改某个元素时,可以把这个位置上的数据取出来放到弹层里(或者其他某个位置),在弹层里的信息可以取消或者修改后进行保存。
原文地址:http://www.xiabingbao.com/vue/2017/07/10/vue-curd.html
假设我们弹层里的数据是selectedlist,那么每次修改时,把index位置的数据给了selectedlist,然后在弹层中修改selectedlist。我们也能看到修改数据的类型: 文本框(用户名,邮箱),单选按钮(性别),select选择框(所在省份),多选框(爱好),这里我们主要练习的是表单处理(https://cn.vuejs.org/v2/guide/forms.html)。弹层是否显示用变量isActive来控制:
// 修改数据
modifyData(index) {
this.selected = index; // 修改的位置
this.selectedlist = this.list[index];
this.isActive = true;
}
有没有发现一个问题,当修改弹层中的信息时,表格中的数据也同步更新了。可是我们本身是希望当点击保存按钮时,才把弹层中的数据保存到表格里。问题的根源就出在这里:
this.selectedlist = this.list[index];
因为list[index]是个Object类型的数据,若使用=赋值,则赋值操作为浅度拷贝(把数据的地址赋值给对应变量,而没有把具体的数据复制给变量,变量会随数据值的变化而变化),selectedlist与list[index]使用相同的数据地址,互相引起数据值的变化。因此这里我们需要进行深度拷贝:
this.selectedlist = JSON.parse( JSON.stringify(this.list[index]) ); // 先转换为字符串,然后再转换
当用户修改数据后,selectedlist就会发生变化,点击保存按钮时,将数据重新保存到index位置:
/*
this.list 数据数组
this.selected 刚才修改的位置
this.selectedlist 需要保存的数据
*/
Vue.set(this.list, this.selected, this.selectedlist);
7:导入 import Vue from 'vue'
8:表单提示:
[Element Warn][Form]model is required for validate to work!
该提示说的是 form表单需要一个绑定一个 对象(使用:model="" 不能使用v-model=""),
9.表单通过父组件传值来disabled表单
首先在给表单添加 :disabled="disabledFlag"属性.
然后接受父组件传递过来的标志位 props: ['disabledFlags'],
然后在给给页面标识位声明一个默认值 disabledFlag:false,
把父组件传过来的值赋值给页面的标志位就可以了.
created(){
this.disabledFlag = this.disabledFlags;
},
10.子组件互相传值
1、兄弟之间传递数据需要借助于事件车,通过事件车的方式传递数据
2、创建一个Vue的实例,让各个兄弟共用同一个事件机制。
3、传递数据方,通过一个事件触发bus.$emit(方法名,传递的数据)。
4、接收数据方,通过mounted(){}触发bus.$on(方法名,function(接收数据的参数){用该组件的数据接收传递过来的数据}),此时函数中的this已经发生了改变,可以使用箭头函数。
步骤:
(1):我们可以创建一个单独的js文件eventVue.js,内容如下
import Vue from 'vue'
export default new Vue
(2)首先都要导入 import bus from "../../components/eventBus.js"
(3):子组件一: var basicsInfo = response.data.basicsInfo; //基本信息
bus.$emit("basicsInfoData",basicsInfo);
发送事件数据
(4):子组件二:
直接写mounted监听 message就是你传递的数据
mounted(){
bus.$on("bankCardInfoData",(message)=>{
console.log("银行卡信息赋值");
this.bankCardInfo= message;
})
},
(5):在有的地方this 是undefined 就要用 _this
5、疑问:我可以让子组件三号发送一号组件的名字然后给二号组件发送数据吗? 待测试.
11.给对象动态添加属性:
bus.$on("modifyFlagData",(message)=>{
console.log("修改标识位");
var modifyFlagArray = message.split('|');
for(var j = 0,len = modifyFlagArray.length; j < len; j++){
_this.modifyFlag[modifyFlagArray[j]]=true;
}
console.log(_this.modifyFlag);
})
12. 子组件之间传值用bus会有多次调用的问题.所以更改调用方式,使用子传给父,父在传给子.子组件用watch监听数据.
子组件一号是用$emit的形式触发
this.$emit("templateData", this.assessmentsData);
父组件:
v-on:是子组件触发的名字 等号后面的是 父组件自己的方法
<query-template v-on:templateData="templateData"></query-template> 使用v-on把事件绑定.
然后在父组件中写一个templateData 的方法. 括号里面就是 你从子组件中传过来的数据.然后把子组件的值赋值给父组件的变量,然后在从父组件 传给子组件二号
templateData(assessmentsData){
this.assessmentsData= assessmentsData;
}
子组件二号:
在子组件二号的标签上加上 v-bind:tempalate="assessmentsData" tempalate就是传递的变量名字.等号后面就是你要传递的变量.
在二号子组件中用prop加上
props: ['tempalate'],
然后在写一个watch(); watch和method平级 在watch 中要加 deep: true !!!
watch: {
tempalate(val, oldValue) {
debugger;
this.assessmentsData = val;
},
deep: true
},
然后val 就是你传递过来的是, oldValue就是之前的值.
用$emit 发送数据
然后用watch监听 这样就能实现子父子的传递参数了.
注意:
1.组件传值的时候 名字要一致.
2.记得watch的时候要写 deep: true.
13.vue.js 统一关闭页面的方法:
调用传递参数:
closeWindow(){
//关闭当前页面
let view = {};
view.path = '/counter/account/servicecentre/riskassessment';
view.name = '风险测评';
this.baseCloseCurrentPage(view)
}
// 公共方法 关闭当前页面
baseCloseCurrentPage(view) {
this.$store.dispatch('delVisitedViews', view).then((views) => {
const latestView = views.slice(-1)[0]
if (latestView) {
this.$router.push(latestView.path)
} else {
this.$router.push('/')
}
})
this.$parent.$router.push({path: view.path})
},
delVisitedViews({ commit, state }, view) {
return new Promise(resolve => {
commit('DEL_VISITED_VIEWS', view)
resolve([...state.visitedViews])
})
},
14.foreach循环 数组本身的索引
forEach方法中的function回调有三个参数:第一个参数是遍历的数组内容,第二个参数是对应的数组索引,第三个参数是数组本身.
[].forEach(function(value,index,array){
//code something
});
例子:
var arr = [1,2,3,4];
arr.forEach(function(value,index,array){
array[index] == value; //结果为true
sum+=value;
});
console.log(sum); //结果为 10
15.前端解决ajax调用异步的问题.
deleteInfo(node, data){
let queryReq = {};
queryReq.orgNo = data.orgNo;
queryReq.queryTemplate = "role_user";
let urlKey = 'common/query/queryDataList';
this.$store.dispatch('EASYPOST', {
'urlKey': urlKey,
data: queryReq
}).then(response => {
this.rowLength = 0;
this.rowLength = response.data.rows.length;
//在这里面直接只用 this.rowLength的时候 值获取的都是上一次的值.
this.confirmTitle(node, data);
}).catch(error => {
this.$message.error(error.message)
})
console.log('length',this.rowLength);
},
//所以就在写一个方法,让它继续执行.在这里米娜在进行判断
confirmTitle(node, data){
let title = '';
if (this.rowLength >0){
title = '角色下有'+this.rowLength+'名员工是否确认要删除?'
}else{
title = '【' + data.label + '】是否确认要删除?'
}
this.$confirm(title, '删除', {
type: 'warning'
}).then(() => {
this.deleteTree(node, data)
}).catch(() => {
})
},
将调用结果嵌套到下一个方法里面.
16.表单的动态校验
:validate-on-rule-change="false"
17.组织数据
let idList = []
if (this.formParams.datas) {
this.formParams.datas.forEach(item => {
idList.push(item.id)
})
}
let request = {
idList: JSON.stringify(idList),
batchLeaveData: this.batchLeaveData.batchLeaveDatas,
}
前端拼成json字符串 --> 后台用String接受.
然后使用 JSONArray split = JSONArray.parseArray(idList);
转成jsonArray 遍历的时候使用 .size
遍历使用的时候 ,直接用 .toString 或者 .getString 方法.
18.前端重置表单
通过refs. 表单的ref属性名 调用resetFields 方法就可以了.
this.$refs.batchLeaveData.resetFields();
用处: 每次进入子组件的时候,表单的信息还在. 自带属性
19.前台弹窗换行:
this.$message({
type: 'success',
dangerouslyUseHTMLString: true,
message: this.$t(response.data)
});
用处:解析后台的<br> 在弹窗内换行.自带属性
20.java / 一个方法需要更新多张表的时候,成功同时成功,失败同时失败.
在总方法上面增加一个
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
注解, 然后调用方法的时候不能使用this. 要用类名.的方式去调用,不然开启的是一个事物.达不到需求.
21.使用多线程的时候注意事项,
抛异常是没有用的.使用logge日志
在线程里面直接是使用SpringUtiles获取Service或biz直接调用.
在service或biz里面使用事物.
新开的线程是不归spring管理的.
22.格式化金额
DecimalFormat decimalFormat = new DecimalFormat("###,##0.00");
dayTradeAckFlowDto.setApplicationAmountStr(decimalFormat.format(dayTradeAckFlowDto.getApplicationAmount()));
23.java地址传递
在多线程的时候,使用地址传递的时候,如果线程内用的是同一个对象,就会产生A线程获取的是B 线程的值.
解决方法,重新new一个对象 传递下去.
24.提交按钮提交多个表单
let transmitFlag = false;
let custData = false;
let transactionId = false;
this.$refs.transmit.validate((valid) => {
if (valid) {
transmitFlag = true;
}
});
this.$refs.custData.validate((valid) => {
if (valid) {
custData = true;
}
});
this.$refs.transactionId.validate((valid) => {
if (valid) {
transactionId = true;
}
});
if (!transmitFlag || !custData || !transactionId) {
return;
}
使用ref属性 form表单要写ref属性 和model一致.
25.mode值有了,但是页面组件并没有显示出来.
<el-form label-position="right" :inline="true" label-width="150px" size="small" :rules="rules" v-if="formType"
:model="salesAppInfo" :disabled=disabledFlag ref="salesAppInfo">
在表单的属性上添加一个v-if属性,然后加一个判断位
默认为true
在watch的时候修改为false 然后在
this.$nextTick(()=>{
this.formType = true
})
中改为true.
例:
investorName(val, oldVal) {
console.log('val',val);
this.salesAppInfo.actualController = val;
this.salesAppInfo.actualEneficiaries = val;
console.log("salesAppInfo",this.salesAppInfo);
this.formType = false;
this.$nextTick(()=>{
this.formType = true
})
},
vue..$nextTick
用法:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
26.表单的动态校验. 显示红色星号 必填
- 思路 使用变量来控制是否校验,但是在data中写rules对象,数值能改, 但是红色必填没有办法动态出现
- 但是不好用,对象的数值能边 .但是 红色的必填星号不行.
- 然后在vue官网支持另一种写法.
-
<el-form-item prop="email" label="邮箱" :rules="[ { required: true, message: '请输入邮箱地址', trigger: 'blur' }, { type: 'email', message: '请输入正确的邮箱地址', trigger: ['blur', 'change'] } ]" >
- 这样就可以实现红色星号的动态校验了.
27.element DatePickerr 日期选择器为什么赋值不成功的解决办法
- 初始页面赋值的时候不用直接把值赋到model上面, 使用 this.$set( ) 方法赋值.因为data组件有一个displayValue属性,与页面展示的属性一直,就不更新model.但是displayValue是一个只读, 所以要更改赋值的地方.
-
可以使用import Vue from 'vue' 然后在调用set方法 也可以使用vue.set的别名this.$set 数组: this.$set(arr, index, val). 对象: this.$set(obj, key, val).
28.刷新当前页面数据
this.$forceUpdate()
29. style="display: flex" 子模块: style="flex: 1" 会根据个数去自动占位
效果:
<el-divider>接口配置</el-divider>
<el-form
:inline="true"
ref="interfaceForm"
:rules="interfaceRules"
:model="interfaceForm"
label-width="100px"
size="mini">
<el-row>
<div v-for="item in interfaceData" :key="item.dictKey" style="display: flex">
<el-checkbox style="flex: 1" v-model="item.enabledFlag" true-label="1" false-label="0"
@change='$forceUpdate()'>
{{ item.dictValue }}
</el-checkbox>
<el-form-item style="flex: 1" label="版本号" :prop="item.dictKey">
<el-input v-model="item.interfaceVersion" @input='$forceUpdate()' maxlength="10"
show-word-limit placeholder="请输入版本号"></el-input>
</el-form-item>
<el-form-item style="flex: 1" label="请求地址前缀" prop="interfaceVersion">
<el-input v-model="item.requestUrlPrefix" @input='$forceUpdate()' maxlength="50"
show-word-limit placeholder="请输入请求地址前缀"></el-input>
</el-form-item>
</div>
</el-row>
</el-form>
30: el-dialog 弹框加滚动条
// 弹框加自定义的 class
<el-dialog :title="title" :visible.sync="open" class="dialogClass">
// 样式属性
.dialogClass .el-dialog__body {
height: 380px;
overflow: auto;
}
31: json页面数据展示 . 可以引入 jsonview组件.
<template>
<div>
<el-dialog :title="title" :visible.sync="open" class="dialogClass">
<pre v-html="json" ></pre>
</el-dialog>
</div>
</template>
<script>
import mapStr from './str/str'
import util from '@/libs/util'
export default {
name: 'jsonView',
created () {
},
data () {
return {
json: '',
title: '消息明细',
open: false
}
},
methods: {
syntaxHighlight: function (data) {
this.open = true
let json = JSON.parse(data)
if (typeof json !== 'string') {
json = JSON.stringify(json, undefined, 2)
}
json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
this.json = json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (match) {
let cls = 'number'
if (/^"/.test(match)) {
if (/:$/.test(match)) {
cls = 'key'
} else {
cls = 'string'
}
} else if (/true|false/.test(match)) {
cls = 'boolean'
} else if (/null/.test(match)) {
cls = 'null'
}
//转换翻译
if (/:$/.test(match)) {
let newVar = mapStr.get(match.replace(':', '').toUpperCase())
if (!util.isEmpty(newVar)) {
match = newVar + ' → ' + match
}
}
return '<span class="' + cls + '">' + match + '</span>'
})
}
},
computed: {}
}
</script>
<style>
pre {
outline: 1px solid #ccc;
padding: 5px;
margin: 5px;
}
.span {
word-wrap: break-word;
word-break: break-all;
overflow: hidden;
white-space: normal;
}
.string {
color: green;
word-break: break-all;
white-space: normal;
}
.number {
color: darkorange;
white-space: normal;
}
.boolean {
color: blue;
}
.null {
color: magenta;
}
.key {
color: red;
}
.dialogClass .el-dialog__body {
height: 380px;
overflow: auto;
}
</style>
32.sql in 超长
-- mapper 代码
<if test="custListGroup != null and custListGroup.size > 0">
and
<foreach item="custList" index="index" collection="custListGroup" open="(" separator="or" close=")">
t.cust_no in
<foreach item="item" index="index" collection="custList" open="(" separator="," close=")">
#{item}
</foreach>
</foreach>
</if>
-- java代码
import com.baomidou.mybatisplus.extension.service.IService;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import org.apache.commons.lang3.StringUtils;
public static List<List<String>> split2List(String value, String separator) {
List<List<String>> custListGroup = new ArrayList<>();
if (StringUtils.isNotBlank(value)) {
custListGroup = Lists.partition(Arrays.stream(value.split(separator))
.collect(Collectors.toList()), IService.DEFAULT_BATCH_SIZE);
}
return custListGroup;
}
public static List<List<String>> split2List(String value) {
return split2List(value, ",");
}