vue中如果报错是这个的话
You cannot set a form field before rendering a field associated with the value.那就是说明后端给的字段和你在input的输入框给的字段要不就是多了要不就是少了,一定要一样。
input的框和后端给的时间不一样的话,只要月份,不要时分秒,但是后端要,然后就报这个错
JSON parse error: Cannot deserialize value of type java.util.Date
from String “2020-07-22T03:31:29.536Z”: expected format “yyyy-MM-dd HH:mm:ss”; nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type java.util.Date
from String “2020-07-22T03:31:29.536Z”: expected format “yyyy-MM-dd HH:mm:ss” at [Source: (PushbackInputStream); line: 1, column: 136] (through reference chain: com.gbiac.empss.modules.energyConsumption.entity.EnergyConsumption[“completedTime”])
这样的解决方式就是在和后端的字段赋值以后添加一个 +"-00 00:00:00" 这样就完美解决了,
this.dataMonth = dateString +"-00 00:00:00"
vuemixins_10">在vue中使用mixins
首先得定义一个混入的对象:例如
export const mixin = {
data () {
return {
num = 1
}
},
created () {
this.hello()
},
hello () {
console.log('hello mixins')
}
}
接下来在组件(1)中引入这个混入的文件
import {myMixin} from '引入的路径'
然后导入
export default {
mixin:{myMixin}
// 生命周期打开页面执行
created () {
// 让混入的文件的num自加
this.num ++
}
}
接下来在组件(2)中引入这个混入的文件
import {myMixin} from '引入的路径'
然后导入
export default {
mixin:{myMixin}
}
vuex_53">mixins和vuex的区别
可以看到在组件一种值改变了,在组件二中没有写那个方法的话值是不会改变的,所以mixins和vuex的区别就是vuex是状态管理,而mixins是定义公用的变量,给每个组件使用,引入组件以后,各个变量是独立的,值的修改不会再组件中相互影响。而vuex是在任何一个组件的值修改,他们其他组件的状态也都会修改。
mixins和公共组件的区别
在父组件中引入组件,相当于在父组件中给出一个独立的空间给子组件使用,然后根据props传值,但是本质倆者是相对独立的,而mixins是在引入组件之后与组件中的对象和方法进行合并,相当于扩展可父组件的对象和方法,也可以理解为是一个新的组件。
注意
键冲突的组件会覆盖混入对象的混入对象中的方法。
当混合里面包含异步请求函数,而我们又需要在组件中使用异步请求函数的返回值时,我们会取不到此返回值,如下
如果在混入中使用异步的话怎么办,那就当传值的时候就用async和awit的方法,具体如下:
这是错误的写法
mixins中:
methods:{
func_one () {
new Promise((resolve, reject) => {
let a = 1
setTimeout (() => {
resolve(a)
},500)
// 因为就一个参数所以箭头函数可以省略小括号
}).then (res => {
console.log(res 'res')
// 这个需要返回值的
return res
})
}
}
组件中:
js">import {mixins} from '引入的路径'
export default {
mixins:[mixins],
mouted () {
console.log(this.func_one(),'这个是错误的写法')
}
}
控制台打印出来的是undefined,这个是错误的写法。
正确的写法:不要返回结果,而是直接返回异步函数。
mixins中:
js">methods: {
async fun_one () {
let result = await new promise ((resolve, reject) => {
setTimeout (() => {
resolve(1)
},800)
})
return result
}
}
组件中:
js">export default {
mixins:[mixins],
mounted () {
this.fun_one().then (res => {
console.log(res,'这是正确的写法')
})
}
}
这样控制台会打印出1,这是正确的写法。
jeccg的前端开发技巧
1、下拉选项错位的解决办法
在a-select标签上边添加一个属性getPopupContainer,值为node => node.parentNode,如果有更深层次的下拉框的话,那就多加几个.parentNode,例如:node=>node.parentNode.parentNode.parentNode
代码示例
<a-select
placeholder="请选择展示模板"
:options="dicts.displayTemplate"
:getPopupContainer="node => node.parentNode"
/>
如果在去掉表单之前的空格直接加.trim
<a-input placeholder="请输入角色编码" v-decorator.trim="[ 'roleCode', validatorRules.roleCode]" />
在jeecg中使用ant design组件的时候,因为这个开源文档就是在ant design一起使用的,当你使用table表格的时候,需要用到编辑到某一项的时候,因为里面就一个input,所以你就需要以下操作了
vue"> <template
v-for="col in ['type','consumer']"
:slot="col"
slot-scope="text, record, index"
>
<div :key="col">
<a-input
v-if="record.editable && col=='type'"
style="margin: -5px 0"
v-model="text"
@change="e => handleChange(record,index, col,text)"
/>
<a-input-number
v-if="record.editable && col=='consumer'"
style="margin: -5px 0"
v-model="text"
@change="e => handleChange(record,index, col,text)"
/>
<template v-if="!record.editable">
{{ text }}
</template>
</div>
</template>
当你写完这个以后,你会发现多了点东西,那你就需要把以下的代码复制上了。一定要注意v-if前面有个感叹号也就是非号。
vue"> <template v-if="!record.editable">
{{ text }}
</template>
继承上一个问题,可以修改值了,但是你会发现点击取消之后的确定以后值不应该是修改的,而是应该返回原来的那个数,那么你就需要把没修改点东西,以下是代码
js">// 在调完接口以后你赋值的是一个数组,但是不修改的话是原来的值,然后oldData就是在data里面定义的空数组,让写原来的值。
data () {
return (
dataOnthe :[],
oldData:[],
)
}
// dataOnethe就是从后端要来的数据
this.dataOnthe = res.result // result是后端返回的数据
// JSON.parse(JSON.stringify(res.result));简称解除vue的双向数据绑定
this.oldData = JSON.parse(JSON.stringify(res.result));
// 在点击取消的时候
cancel(key,index) {
console.log(key,index)
const newData = [...this.dataOnthe];
// console.log(this.oldData)
const target = newData[index];
// this.editingKey = '';
// console.log(target)
delete target.editable;
console.log(this.oldData)
this.dataOnthe= JSON.parse(JSON.stringify(this.oldData));
// this.data[index]=this.oldData[index];
},
在table中默认是展示10行的,然后会自动有第二页的数据,如果你需要修改第二页里面的值的话你就会发现不能修改,那么有俩种办法,可以修改,第一种那就是最简单的不要分页器,第二种我也不会,需要把index的索引给传过去,先不弄。
今天学到的东西,今天有幸接触到一个react做完的项目,然后还是用echarts图表写的,因为所有的数据都是后端返回来的,所以不知道该怎么渲染,因为需求是加一个按钮,怎么加怎么不对,查看文档也懵懵懂懂的,后来经过一番研究,终于知道当你写一个按钮的时候,你写上他然后图表就没了,所以你得给图表一个高度,但是当你给了高度你就会发现图表的样子改变了,因为jsx中必须得有一个父元素,所以你把按钮个循环的所有值包裹起来以后,你给那个父元素宽和高就OK。以下是代码
js"> <div className="benchmarking-content">
{this.state.chart.map((item,index)=> // 这是循环的图表
(
<div style={{ width:'100%'}}>
<div className='cc' >
<Button className='hh' size="small" onClick={this.showModal.bind(this,index)}>对标分析</Button> // 这是我添加的按钮
</div>
<div ref={'echarts'+index} className="benchmarking-chart" style={{ height:'100%'}} key={index}></div>
</div>
)
)}
</div>
今天学到的东西
用echarts图表的时候,本来以前的项目显示的是一个柱子,现在让默认显示的是三个,没思路,我们公司的大佬告了我一下,因为刚在echarts拿到的官方示例是这样的
js">option = {
legend: {},
tooltip: {},
dataset: {
source: [
['product', '2015', '2016', '2017'],
['Matcha Latte', 43.3, 85.8, 93.7],
['Milk Tea', 83.1, 73.4, 55.1],
['Cheese Cocoa', 86.4, 65.2, 82.5],
['Walnut Brownie', 72.4, 53.9, 39.1]
]
},
xAxis: {type: 'category'},
yAxis: {},
// Declare several bar series, each will be mapped
// to a column of dataset.source by default.
series: [
{type: 'bar'},
{type: 'bar'},
{type: 'bar'}
]
};
这只是死的数据,然后默认显示的也是三个,但是数据不一样怎么办呢,因为以前的是循环的,所以现在需要显示的值是后台数据给的,那怎么办呢,看到这个示例我们知道需要改source的数据,那怎么改呢
js">if(res.success){
this.setState({
chart:res.result.chart,
dataSource:res.result.table.data,
columns:res.result.table.title,
},
function () {
for(let i=0; i<this.state.chart.length;i++){
let item = this.state.chart[i];
let arr=[];
for(let j=0;j<item.value.length;j++){
// 这就是拼接的一个数据了,按照echarts的source里面需要的数据,拼接的,
{this.state.timeMode == 1?arr.push([item.name[j],item.value[j].reality,item.value[j].benchmark,item.value[j].target]):arr.push([item.name[j],item.value[j].reality,item.value[j].benchmark,item.value[j].mon])}
// if(j%2 ==0){ 这些以前是显示一根柱子的数据
// barData.push({
// // 显示三个值
// value:item.value[j],
// value:item.value[j].reality,
// value:item.value[j].target,
// itemStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
// offset: 0,
// color: "#47CAFD"
// },
// {
// offset: 1,
// color: "#5162F1"
// }
// ])
// },
// })
// }else{
// barData.push({
// value:item.value[j],
// itemStyle: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
// offset: 0,
// color: "#95E283"
// },
// {
// offset: 1,
// color: "#38B269"
// }
// ])
// }
// })
// }
}
// 这儿这个三元表达式是因为我们公司年和月需要的值不一样所以我写一个三元表达式,这就是echarts的source下的product得值
{this.state.timeMode == 1?arr.unshift(['product', '实际值', '基准值', '目标值']):arr.unshift(['product', '实际值', '基准值', '环比'])}
// 单位旅客吞吐量耗水量
let echarts1= this.refs[`echarts`+i];
let tceCharts1 = echarts.init(echarts1);
let option1 = {
title:{
text:item.tilte,
// right: "100%",
textStyle:{
color:"#fff",
fontSize: '12rem'
}
},
// color: ['#3398DB'], //柱子颜色
// // color: ['#3FB7A0','#5162F1'],
color:["#47CAFD","#38B269","#5162F1"],
tooltip: { // 如果不设置的话不会占满空间 和grid一起使用
trigger: 'axis',
},
grid: {
top:"15%",
left: '3%',
right: '4%',
bottom: '3%',
containLabel: true
},
// xAxis : [
// {
// type : 'category',
// data :item.name,
// axisTick: {
// alignWithLabel: true
// },
// axisLabel:{
// interval:0,
// },
// axisLine:{
// lineStyle:{
// color:"#73737D",
// }
// }
// }
// ],
yAxis : [
{
type : 'value', // 坐标轴类型
min:0,
axisLabel:{ // 坐标轴刻度标签的相关设置。
color:"#73737D",
},
axisLine:{ // 坐标轴轴线相关设置。
lineStyle:{
color:"#73737D",
}
},
splitLine:{ //
lineStyle:{
color:"#73737D",
}
}
}
],
// series : [
// {
// name:"",
// type:'bar',
// type:'bar',
// type:'bar',
// barWidth: '30',
// data:barData
// },
// ]
legend: {},
tooltip: {},
dataset: {
source:arr // 这儿直接把arr的值赋给这个echarts的值就ok了。
// [
// [ , item.value[0].reality,item.value[0].benchmark, item.value[0].target],
// // ['Milk Tea', 83.1, 73.4, 55.1],
// // ['Cheese Cocoa', 86.4, 65.2, 82.5],
// // ['Walnut Brownie', 72.4, 53.9, 39.1]
// ]
},
xAxis: {
type: 'category',
axisTick: {
alignWithLabel: true
},
axisLabel:{
interval:0,
},
axisLine:{
lineStyle:{
color:"#73737D",
}
}
},
series: [
{type: 'bar'},
{type: 'bar'},
{type: 'bar'}
]
};
tceCharts1.setOption(option1);
var picInfo = tceCharts1.getImage();
alert(picInfo)
tceCharts1.resize();
console.log(barData)
}
react使用echarts点击一个按钮的时候获取图片传到另一个div里面
js">// 获取画布
var canvas = document.getElementsByTagName("canvas");
console.log(this.state.dataImageCanvas,oA)
if(canvas&&canvas.length>0){
// 获取标签
var oA = document.getElementById("imageData");
// 设置地址以及文件类型
oA = canvas[e].toDataURL("image/png");
console.log(oA)
this.setState({
// 再初始的state里面的定义的是null
dataImageCanvas: oA
})
}
react的打印功能
js"> print = (e) => {
console.log(e)
// 这是要打印的页面元素用一个div包起来,然后给一个唯一的id,那打印的就是这个div里面的所有的元素
window.document.body.innerHTML = window.document.getElementById('div_print').innerHTML;
window.print();
window.location.reload();
}
项目难点
在react中使用antdesign组件的model配合echarts使用的时候,需要通过他的下标来获取每一项,那么怎么获取呢,先在点击的时候传值过来,因为所有的数据都是后端生成循环过来的
js">{this.state.chart.map((item,index)=>
(
<div style={{ width:'100%'}}>
<div className='cc' >
// 传的值就是index,加this是因为如果不加的话他会自调用,加上this就不会了。
{<Button className='hh' size="small" onClick={this.showModal.bind(this,index)}>对标分析</Button>}
</div>
<div ref={'echarts'+index} className="benchmarking-chart" style={{ height:'100%'}} key={index}></div>
</div>
)
)}
然后把他的每一项传给点击打开的model
js">// 接收那个默认的形参index
showModal = (e) => {
// debugger; 获取到value值以后如果value的那个数组里边没有值的话就不执行
if (this.state.chart[e].value.length > 1) {
// console.log('下标:',e)
this.setState({
visible: true,
// 这是在赋值每一个chart
chartData:this.state.chart[e],
// 这是赋值每一个chart下的每一项的results
chartData1:this.state.chart[e].results[e],//results[e]
// 这是赋值每一个chart下的每一项的name
chartData2:this.state.chart[e].name[e],
chartData3:"", // 因为需求需要渲染页面的时候显示或者不显示,所以还需要一个空值,显示的不一样,渲染的也不一样
chartData4:""
});
// 在这儿就是点击按钮的时候通过下标,点击的时候name(是个数组)的长度大于一就显示其他的。
if (this.state.chart[e].name.length > 1) {
// 通过下标来获取点击的是哪个就渲染哪个
let index = 0;
if( e === 0 ){
index = 1
}
this.setState({
// 让这个空值等于这个name点击的下标
chartData3:this.state.chart[e].name[index],//string,这就是点击之后让渲染的不一样的值
})
}
if (this.state.chart[e].results.length > 1) {
let index1 =0;
if(e===0){
index1=1
}
this.setState({
chartData4:this.state.chart[e].results[index1],//results[e]
})
}
} else {
return message.warning('无法对标')
}
};
上边这种方式只能默认显示俩个,下边的话有多少显示多少
js">// 里面的数据都是后端返回然后定义的
chartData:{name:[],results:[],title:"",value:[]},
{this.state.timeMode == 1?<span><strong>{this.state.comparisonDateString }</strong>年度,
{this.state.chartData.name.map((item,index) => (
// index就是下标也就是每一项
<span><strong>{item}</strong>的年度机场吞吐量综合能耗为<strong>{this.state.chartData.results[index].nowTce + 'tce'}</strong>,</span>
))}
//这样item就是每一个名字,results就是另一个数据但是[index]是每一项,也就是name的index因为点击哪个出现的是哪个数据,多个的话就显示多个
当你在react中使用map循环的时候,报错为map为undefined的时候,说明你定义的数据不是一个对象,或者你赋值的时候,没赋值上数组的值,那你就在state中定义的时候把后端拿的数据定义一下,是什么类型的就定义什么类型的。
js">// 后端返回的数据,有什么定义什么
chartData:{name:[],results:[],title:"",value:[]},
js"><li>
{/* 年度综合能耗 */}
{this.state.timeMode == 1?<span>{this.state.comparisonDateString }年度,
{this.state.chartData.name.map((item,index) => (
<span>{item}的年度机场吞吐量综合能耗为{this.state.chartData.results[index].nowTce + 'tce'},</span>
))}
{/* 月度综合能耗 */}
</span>:<span>{this.state.comparisonDateString}月度,
{this.state.chartData.name.map((item,index) => (
<span>{item}的月度机场吞吐量综合能耗为{this.state.chartData.results[index].nowTce + 'tce'},</span>
))}
</span>}
</li>
js中整数转负数
js">javascript Math.abs();
console.log(Math.abs(-10));