前端实习周记12
最后一周的实习,主要把我之前写的页面根据需求又继续完善了不少,忙碌了几天,但是也学到了很多
组件传递对象及相应点击事件修改
需求:原本的业务实现是,点击右侧多选树形列表,将被点击的公司ID传递给左侧统一发请求的组件,现在需要点击获取公司ID及公司名称并传递给发请求的组件和展示echarts图的组件(legend根据是否多选显示公司名称)
实现:
-
列表组件中的state:包含每一个被点击公司ID的数组=》每一个被点击的公司ID及公司名组成的对象而形成的数组
const [selectContent, setSelectContent] = useState([]) //更新树形结构状态 setSelectContent([{ entId: treeData[0] && treeData[0].children[0].entId, entName: treeData[0] && treeData[0].children[0].title }]); //树形结构选择 const onSelect=(keys,info)=>{ if(!info.node.children){//处于树形结构最后一层 //数组不为空逻辑修改 const notNull=selectedContent.some(item=>{ return item.entId==info.node.entId }) if(notNull && selectedContent.length!==1){ selectedContent=selectContent.filter(item=>item.entId !== info.node.entId) else if (selectedContent.length < 2 && !notNUll) { selectedContent.push({ entId: info.node.entId, entName: info.node.title }) } } } -
接口请求参数变化
//原先 const rankData= await getRank({ ent_id:entId[0] }) //现在 const rankData=await getRank{ ent_id:entValue[0].entId }
Set取两个数组的交集
需求: 当从树形结构选择列表时,选择主企业时只展示主企业的设备类型,选择主副企业时,展示两个企业的交集
实现:
const [devType, setDevType] = useState([])
//处理主副企业设备类型交集
const convertDevType=(pre,cur)=>{
if(entValue?.length===1){
setDevType([])
}
let arrSet=new Set([...pre,...cur])
setDevType([...arrSet])
}
//获取完接口数据后
setData(data)
convertDevType(devType,data.dev_type)
多个请求优化
一个页面同时发送多个请求,使用promise.all优化
const getData = async ()=>{
const promises=[
getxxx({...}),
getxxx({...}),
getxxx({...}),
]
const [xxdata,xxdata,xxdata]=await promise.all(promises)
setxxData(xxdata)...
}
ECharts根据点击数据判断展示
需求:当用户点选中一个企业时,只展示一条折线,当用户选中两个企业时,展示两条折线
实现:
根据原本页面逻辑,先在组件外提前设置好option,在组件内根据接口获取到的数据再对option进行更新,这里主要修改的是更新option的部分,主要对list进行修改
由于后端接口每次只能传递一个企业id获取到一个企业的数据,所以我打算使用state将当用户只点选了一个企业时,将该企业的数据存到组件的state中;当后续用户点击了两个企业时,第一条展示的数据就是原先存储的数据
const [preList, setPreList] = useState([]);
const list = []
if (devName) {
if (entValue.length === 1) {
list.push({
name: `${devName}: ${entValue[0].entName}`,
data: entData.data_info[devName]
})
setPreList(entData.data_info[devName])
} else {
list.push({
name: `${devName}: ${entValue[0].entName}`,
data: preList //state中之前存储的数据
})
list.push({
name: `${devName}: ${entValue[1].entName}`,
data: entData.data_info[devName]
})
}
}
按照这个逻辑写应该是没有问题,但是在测试的时候发现preList只有一次获取到了数据,当展现两条数据时,preList为初始化的值,经过排查发现是因为当用户点击选择了两个企业时,页面重新刷新导致state默认为初始化的数值 ,解决方法:将state写到该组件的父组件当中,通过props传递
本地缓存列表逻辑优化
在修改多选复选逻辑的时候,发现自己写的获取列表进行缓存的逻辑有些不太完善,修改:
//获取列表请求
const getEntData = async (entName, localName, tap) => {
const entDataList = localStorage.getItem(localName)
let pretreeData
if (entDataList) {//之前已有本地缓存
const res = JSON.parse(entDataList)
pretreeData = generateTree(res)
}//无本地缓存
const res = await getEnterpriseData({
group_by: tap,
ent_name: entName
})
if (entDataList !== JSON.stringify(res)) {//本地缓存与接口返回不一致
const treedata = generateTree(res)
updateTreeData(treedata)
localStorage.setItem(localName, JSON.stringify(res))
return
}
//本地缓存与接口返回一致
updateTreeData(pretreeData)
}
useRef存储不会重新引发渲染
在使用useState,如果state更改的时候就会重新引发渲染,目前的需求只是为了存储数据判断获取初次页面加载的数据,并不希望引发多次渲染页面造成不必要的发送请求,所以可以使用useRef来做:
const initialDev = useRef(null)
useEffect(() => {
setLoading(true)
if (entValue) {
getDevType()
if(initialDev.current || paramsData.dev_type){
getData()}
}
}, [entValue,initialDev.current])
const getDevType = async () => {
if (entValue.length === 1) {
const res = await getAnalysisDeviceType({
ent_id: lastEntValue.entId,
})
setParamsData(state => ({
...state,
dev_type: res[0].dev_type
}));
setDevType(res)
initialDev.current = res[0].dev_type
}
}