SPC项目总结
一、树形结构(< el-tree>< /el-tree>)
如下。详细情况查看链接(vue-elementui)
1.数组转树形
最开始 使用树形结构,是获取全部数据,然后将数组转为树形结构(
[{id:'',children[id:"",children:[]]}]
)。
const data=[
{partentId: "0",name: "Luxsan2", id: "271665283503099904"},
{partentId: "0",name: "A5",id: "261142640031043584"},
{partentId: "261142640031043584",name: "A5-1",id: "261142640031043586"},
{partentId: "261142640031043586",name: "A5-1-1",id: "261142640031043589"}
]
// 数组转树形
toTree (data) {
let treeData = [];
if (!Array.isArray(data)) return treeData;
let map = {};
data.forEach(item => {
map[item.id] = item;
});
data.forEach(item => {
let parent = map[item?.partentId || item.folderId]; //判断item的partentId是否是否存在map中
if (item.partentId === '0') {
treeData.push(item) // 如果为0 则是顶层数据
}
if (parent) {
item.partentIdname = map[item?.partentId || item.folderId].name;
(parent.children || (parent.children = [])).push(item)
} //如果存在则表示item不是最顶层的数据
});
return treeData;
},
2.懒加载(推荐)
后来 使用
:load="loadNode" lazy
来实现树形结构的懒加载 。
目的:是为了当树形结构数据量很大的时候,防止加载很慢
推荐使用懒加载
<el-tree :data="data" node-key="id"
:load="loadNode" lazy
:default-expanded-keys="[currentKey]"
:current-node-key="currentKey"
:filter-node-method="filterNode"
:props="defaultProps"
ref='tree'
highlight-current
@node-click="nodeClick">
//懒加载节点
loadNode (node, resolve) {
switch (node.data.remark) {
case 'mpc':
getMpcDefList({ enabled: 1, folderId: node.data.id, partentId: "0" }).then(res => { return resolve(res.result); });
break;
case 'spc':
getEntityListSpcChannelDef({ enabled: 1, folderId: node.data.id }).then(res => { return resolve(res.result); })
break;
default:
getEntityListSpcFolder({ enabled: 1, partentId: node.data?.id || "0" }).then(res => { return resolve(res.result); })
}
},
3.刷新树节点
//获取创建的目录树
refreshNodeBy (id) {
let node = this.$refs.tree.getNode(id);
//node 有值 ....
if (node) {
node.loaded = false;
node.expand(); // 主动调用展开节点方法,重新查询该节点下的所有子节点
}
},
4.刷新最外层节点(不使用window.reload方法进行无感刷新)
因为没有办法使用refreshNodeBy 方法,所以决定刷新整个页面
原因:refreshNodeBy 是刷新子节点的,由于最外层节点没有没有父节点,所以自己没办法刷新。所以决定刷新整个页面。
不使用window.reload方法进行无感刷新
1.进入App.vue
2.进入要刷新的页面
成对出现:
provide
和inject
是成对出现的
作用:用于父组件向子孙组件传递数据
使用方法:provide
在父组件中返回要传给下级的数据,inject
在需要使用这个数据的子辈组件或者孙辈等下级组件中注入数据。
使用场景:由于vue有$parent属性可以让子组件访问父组件。但孙组件想要访问祖先组件就比较困难。通过provide/inject
可以轻松实现跨级访问父组件的数据
使用:this.reload()
即可
5.自定义树节点高亮
节点刷新后,先前选中的树节点高亮消失。会忘记前面user的操作。
所以:进行重新设定选中数据–树节点高亮。需设定属性如下:
node-key="id" :current-node-key="currentKey" :default-expanded-keys="[currentKey]" highlight-current
this.$nextTick(() => {
this.currentKey = this.paramData?.id || '';//获取需要高亮的id进行赋值
this.$refs.tree?.setCurrentKey(this.currentKey);
})
6.树形控件样式
右侧红色部分 ,当树节点部分需要的操作多的时候,用下拉框
<el-dropdown>
进行设定
使用事件
command
--点击菜单项触发的事件回调 dropdown-item 的指令
<el-tree :data="data">
<div class="custom-tree-node" slot-scope="{ node, data }" style="width:100%">
<span class="tree-label">
<i class="el-icon-folder"></i>
{{ node.label }}
</span>
<span class="tree-icon">
<el-dropdown @command="handleCommand" szie="mini" v-if="!data.folderId">
<span class="el-dropdown-link">
<i class="el-icon-arrow-down"></i>
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item :command="{data:data,value:'ldsfolder'}">新建 LDS文件夹</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</span>
</div>
</el-tree>
二、正态分布图
组成部分是由 正态分布图+直方图。
正态分布图逻辑:正常情况—x:数据;y:概率密度(因为我的是倒着的,所以取反就好)
直方图逻辑:确定组数和组距,得到某个区间内数值个数
1.正态分布图
1.概率密度计算
//正态分布数据
normalDistribution (value) {
let res = []; // 正态分布数据
//原始值排序
let result = value.sort((x, y) => x - y);
// 标准差
// 1.求平均值
let sum = value.reduce((prev, curr) => prev + curr);
const avg = sum / value.length
//2.返回偏差。 f(x) = x - avg
const dev = value.map(x => x - avg);
//3.求偏差平方和
const sumOfSquOfDev = dev.map(x => x * x).reduce((x, y) => x + y);
// 4.返回方差
const variance = sumOfSquOfDev / (value.length - 1)
//5.开根号获取标准差
const stdev = Math.sqrt(variance)
result.forEach(i => {
let a = 1 / (Math.sqrt(2 * Math.PI) * stdev);
let b = Math.pow(Math.E, -(Math.pow(i - avg, 2) / (2 * Math.pow(stdev, 2))));
const fx = a * b;
res.push([fx, i]);//fx:概率密度,i:数值
});
return res
},
//series内部
{
name: '正态分布', // y 轴名称
type: 'line', // y 轴类型
symbol: 'none', //去掉折线图中的节点
smooth: true, //true 为平滑曲线
data: normalDistribution, // y 轴数据 -- 正态分布
xAxisIndex: 1,
yAxisIndex: 0,
},
2.直方图
//直方图数据
histogram (value, key) {
let res = [];
const min = Math.min.apply(null, value);//获取数据最小 最大值
const max = Math.max.apply(null, value);
// 组数K
let k = Math.ceil(1 + Math.log10(value.length) / Math.log10(2));
// 组距
let r = (max - min) / k;
for (let i = min - r; i <= max + r; i = i + r) {
let count = 0;
value.forEach(element => {
if (element >= i && element < i + r) {
count += 1;
}
});
// count 不为0 [x起始位置,x结束位置,y结束位置,y起始位置]
if (count) res.push([0, count, i + r, i]);
}
return res;
},
直方图的实现是利用echarts 的自定义图形实现
//series内部
{
name: '直方图',
// type: 'bar',
type: 'custom',
renderItem: function (params, api) {
// params 坐标系信息及数据信息,api 方法信息
//例:0,2,-25,-32----x1,x2,y1,y2
let coord = api.coord([api.value(0), api.value(2)]);
//api.size([2, 4]) 返回 [12.4, 55],表示 x 轴数据范围为 2 映射得到长度是 12.4,y 轴数据范围为 4 时应设得到长度为 55。
let size = api.size([api.value(1), api.value(2) - api.value(3)]);
let style = api.style();
const res = {
type: 'rect',
shape: {
x: coord[0],//coord[0] 指x的像素起始位置
y: coord[1],//coord[1] 指y的像素起始位置
width: size[0],//size[0] 指x的长度
height: size[1],//size[1] 指y的长度
},
style: style
};
return res
},
label: {
show: true,
rotate: -90,
// position: 'top'
formatter: function (data) {
return data.data[1]
}
},
dimensions: ['start', 'profit', 'from', 'to'],
encode: {
x: [0, 1],
y: [2, 3],
tooltip: [0, 1, 2, 3],
itemName: 1
},
data: histogram,
xAxisIndex: 0,
yAxisIndex: 0,
markLine: markLine
}
三、杂碎知识点
1.子组件调用父组件方法
<!--父组件-->
<lds-folder-setting @changeChannelSetting='changeChannelSetting' />
//子组件
this.$emit('changeChannelSetting');
2.父组件调用子组件方法
使用穿梭框时为了获取到值。由于提交按钮是在父组件,所以需要在提交之前获取到穿梭框的值
原因: 穿梭框的v-model 绑定值不能用父组件parmasData.sync绑定。报异常Avoid mutating a prop directly since the value will be overwritten whenever the parent component re-renders. Instead, use a data or computed property based on the prop's value. Prop being mutated: "paramData"
总结:不能修改或者说双向绑定来自父组件的数据
<!--父组件-->
<spc-rule-setting ref='spcrule' />
//调用
this.$refs.spcrule.changKey();
//子组件内部方法
changKey () {
let tempArr = [];
this.keyRelations_.forEach(item => {
this.keyRelationsList.forEach(element => {
if (item === element.keyName) {
const { keyName, keyValue, sortCode } = element
tempArr.push({ keyName, keyValue, enabled: 1, sortCode });
}
})
})
//修改父组件keyRelations值
this.$emit('update:keyRelations', tempArr);
},
3.form表单自校验必填
:rules="ruleValidate" :model="paramData" ref="paramData" prop="name"
<el-form class="top-check clearFix" :model="paramData" ref="paramData" label-width="80px" size="mini" :rules="ruleValidate">
<el-form-item label="Name" prop="name">
<el-input type="text" v-model="paramData.name"></el-input>
</el-form-item>
</el-form>
data(){
return {
// 验证实体
ruleValidate: {
name: [
{ required: true, message: 'Name is Required' }
],
},
}
}
//方法内部校验
commit(){
this.$refs.paramData.validate((valid) => {
if (valid) {
}
})
}
4.两个数组合并(concat)
result.concat(settingResult)
const result =[1,2,3];
const settingResult=[4,5,6]
console.log(result.concat(settingResult));//[1,2,3,4,5,6]
5.数组sort排序
sort() 方法用于对数组的元素进行排序。排序顺序可以是字母或数字,并按升序或降序。默认排序顺序为按字母升序。
注意:当数字是按字母顺序排列时"40"将排在"5"前面。使用数字排序,你必须通过一个函数作为参数来调用。函数指定数字是按照升序还是降序排列。
返回值----Array----请注意,数组在原数组上进行排序,不生成副本。
this.keyRelationsList.sort((x, y) => {
return x.id > y.id ? 1 : -1
})
6.判断是否为数组类型
1.intenanceof
const temp =[];
console.log(temp typeof Array);//false;
console.log(temp typeof Object);//true;
console.log(temp instanceof Array);//true;
console.log(temp instanceof Object);//true;
//以上 因为Array是Object的字类
const temp ={};
console.log(temp typeof Array);//true;
console.log(temp typeof Object);//true;
console.log(temp instanceof Array);//false;
console.log(temp instanceof Object);//true;
instanceof 与typeof 的区别
instanceof和typeof是两个运算符。
在程序设计中用到,常用来判断一个变量是否为空,或者是什么类型的。
typeof是一个一元运算,放在一个运算数之前,运算数可以是任意类型。
返回值是一个字符串,该字符串说明运算数的类型。
typeof 一般只能返回如下几个结果:number,boolean,string,function,object,undefined。一般可以使用 typeof 来获取一个变量是否存在。
如if(typeof a!="undefined"){alert("ok")}
,而不要去使用 if(a) 因为如果 a 不存在(未声明)则会出错。
对于 Array,Null 等特殊对象使用 typeof 一律返回 object,这正是 typeof 的局限性。
instanceof 用于判断一个变量是否某个对象的实例。
a instanceof b?alert(“true”):alert(“false”); //a是b的实例?真:假
如var a=new Array();alert(a instanceof Array);
会返回 true,
同时alert(a instanceof Object)
也会返回 true;这是因为 Array 是 object 的子类。
2.Array.isArray()