前端实习周记7、8

166 阅读4分钟

前端实习周记7、8

echarts相关

配置属性

  • label

    显示数据格式,可以使用formatter进行转换

    label:{
    show:true,
    formatter:'{b}({d}%)'
    }
    

可以用{value}表示,如为字符串则为轴的数值;如为函数,可根据官网配置

  • tooltip

    使用tooltip自定义展示所想要展示的数据,打印出params查看其属性自行配置

使用K线图模拟折线图上柱状图

需求:实现如图所示的折线图上有柱状图上升下降

同环比.png

一开始计划使用echarts中的阶梯瀑布图,但是该图无法实现需求中需要的向下的柱状图,遂考虑使用echarts的K线图,但K线图的定义和使用与需求并不完全匹配,K线图中一个柱状的数据是一个数组,其中包含四个参数:[开盘价、收盘价、最高价、最低价],如果要按照图例中表示上升和下降,需要定义一个基准数据(图上为折线图的数据):

[
    [67,55,55,55] //以开盘价>其他数值 表示柱状图上升
    [67,55,67,67] //以收盘价<其他数值 表示柱状图下降
]

如此便实现图中效果且不展示K线图中的K线,但有一个缺点:不能实现图例中上升下降的颜色变化,因为K线图中的上升和下降表示的含义与这里不同。

改变了图中展示方式后,写了一个遍历判断生成dataset的方法,由于后端返回的同环比数据是以正负数表示的,所有需要遍历判断不同处理

function calculateArray(a, b) { //a原数据 b带有正负的同环比数据
  if (!a) return
  const n = a?.length  //原数据长度==生成的二维数组的长度
  const c = []
​
  for (let i = 0; i < n; i++) {
    const newArray = []
    if (b[i] === 0) {
      newArray.push(a[i], a[i], a[i], a[i])
    } else if (b[i] > 0) {
      newArray.push(a[i] + b[i], a[i], a[i], a[i])
    } else {
      newArray.push(a[i], a[i] + b[i], a[i], a[i])
    }
    c.push(newArray)
  }
​
  return c
}
const data=[20,20,20]
const ringdata=[5,-5,0]
const res=calculateArray(data,ringdata);
console.log(res)
/*[ [25,20,20,20],
    [20,15,20,20],
    [20,20,20,20]] 
*/

接着,用户鼠标移动到图上的描述tooltip也要修改:

 //labelType变量为用户选择的是“同比”还是"环比“
formatter: function (params) {
      const label=params[1].data[1]-params[1].data[3] > 0 ? `${labelType}上升` : `${labelType}下降`;
      const value= label===`${labelType}上升` ? params[1].data[1]-params[1].data[3] : params[1].data[3]-params[1].data[2]
      return params[0].marker + params[0].seriesName + ':' + params[0].value
        + '<br/>' + params[1].marker+`${label}`+':'+`${value}`
  },

树形列表点击传递id不生效

bug : 在树形中点击属性列表没有写传递ID的事件,且为了实现页面加载默认选择列表的第一个项目时用了useEffect每次都默认绑定了固定的id(这可想而知的错误,就导致了每次刷新页面项目的ID都不会变……)

解决方法:

给每次点击项目列表都添加点击获取到ID的事件

  const onSelect = (keys, info) => {
    if (!info.node.children) {
      setSelectedKeys(keys)
      props.click(info.node.entId)
    }
  }

但这里也出现了一个问题:id仍然没有传递过去,或是传递的id显示"undefined"这是因为一开始调用接口获取到id数据时需要一定时间,所以需要约束

const [paramsData, setParamsData] = useState({
        entId: entId&&entId ...  //双重&&判断存在,也可以使用entId && entId.length
      })
      useEffect(()=>{
        if(entId){
          getData()
        }    
      },[entId]) //useEffect依赖项以及if判断const getData=()=>{
    if(entId){
        ...
    }
}

树形结构多选

需求:树形结构多选获取id值,再次点击取消多选,删除id值,默认获取列表第一个id

antd有自带api,但需要按住ctrl键才能实现多选,遂自己实现,最好的实现方式应该是直接在生成树结构 时,用属性中的key:id

return{
    title:...
    key:t.entId
}

但这次因为任务时间紧迫,没有办法再重构代码,于是只好在生成代码的部分给node加一个entId的属性:

 const [selectedKeys, setSelectedKeys] = useState(['0-0-0'])
 const [selectId,setSelectId]=useState([])
return{
    title:...,
    key:t.entId,
    entId: t.ent_id,
}
 props.click(treeData[0].children[0].entId)  //一点击就传递id给父组件
 setSelectId([treeData?.[0].children[0].entId]) //重置点击的id数组
 setSelectedKeys([treeData?.[0].children[0].key]) //重置点击状态

但这样做也有个很麻烦的地方,就是再写树形结构选择事件时,要写两次方法-key和id的方法

 // 树形组件选择
  const onSelect = (keys, info) => {
      //如果不存在点击了的节点,默认选中为第一个
    if (!info.node.children) {
      let selectedIds = selectId  //这里不能直接setState,因为setState是异步的,需要等到下一次页面更新的时候才会更新
      
      if(selectedKeys.length===0){
        setSelectedKeys([['0-0-0']])
        
      }
      //keys-如果选中已有的节点(取消选中)
      if(selectedKeys.includes(keys[0]) && selectedKeys.length !== 1){
        const filterarr=selectedKeys.filter(item=>item!==keys[0]);
        setSelectedKeys(filterarr)//选中未包含的节点
      }else if(!selectedKeys.includes(keys[0])){
        setSelectedKeys([...selectedKeys,keys[0]])
​
      }
     //ids-如果选中已有的节点(取消选中)
      if(selectedIds.includes(info.node.entId) && selectedIds.length !== 1){
        selectedIds= selectedIds.filter(item=>item!==info.node.entId);
      }else{//选中未包含的节点
        selectedIds.push(info.node.entId)
      }
      const aa = new Set([...selectedIds])
      setSelectId([...aa])
      
    }
  }
  useEffect(() => {
    props.click(selectId)
  }, [selectId])
  • 新增需求:

限制多选数量为3——if条件判断

 const filterarr=selectedKeys.filter(item=>item!==keys[0]);
        setSelectedKeys(filterarr)
      }else if(!selectedKeys.includes(keys[0])&& selectedKeys.length<3){
        setSelectedKeys([...selectedKeys,keys[0]])
      }
      if(selectedIds.includes(info.node.entId) && selectedIds.length !== 1){
        selectedIds= selectedIds.filter(item=>item!==info.node.entId);
      }else if(selectedIds.length<3){
        selectedIds.push(info.node.entId)
      }

下拉选择确保字段存在

需求:实现下拉选择,value根据后端传来的数据确定

实现:

 const [devType,setDevType]=useState([]) //初始化state
 
 //处理设备类型
  const convertOptions = (arr) => {
    return arr.map(item => ({
      value: String(item.dev_type),
      label: item.dev_type_name,
    }));
  }
​
  useEffect(() => {  //三重判断确保数据存在才执行
      if(entData && entData.dev_type && entData.dev_type.length > 0){
       const converted= convertOptions(entData.dev_type)       
        setDevType(converted)
      }
  }, [entData]);
​
return (<Select
          allowClear
          placeholder={`请选择`}
          defaultValue="企业总电"
          options={devType}>
​
          </Select>)

Button实现多选按钮、样式切换

需求:包裹着echarts图的容器标题上显示可以多选的button,根据button状态判断是否展示echarts图的某个折线图

实现:

 const [areaOn,setAreaOn]=useState(false)

  const AreaHandleClick = () => {
    setAreaOn(prev => !prev);
  }
 
  return(
  <Button
            type={areaOn ? 'primary':'default'}  //不要求样式的话可以直接这么判断
            onClick={AreaHandleClick}
            >区均值</Button>
  )
​