实习开发总结

2,168 阅读8分钟

前言

本人因所在地四月疫情原因,导致无法在京的实习因为延期无法到达而遗憾收场。在学校度过了两个月,最后在暑假在家附近找了一个公司来前端实习,距今已经有将近四个月了,在这里工作氛围很好,leader也待人和善,但是在这里呆了四个月,我最终决定结束实习,展望未来,迎接春招。

公司主要技术栈

  1. 框架使用的是react16.8以后的函数式组件开发。
  2. 使用了umi框架,进行了一些权限设置、路由设置、和接口请求封装。
  3. 组件库使用的是antd,4x的版本。

离开原因

  1. 公司业务较为重复,不利于未来发展。 我所在的公司,业务一般都是面向后台管理系统 + 首页门户的模式,大多数都是表单的格式,来进行后台数据的管理,没有自己的产品。
  2. 同学喜迎offer,心中略有不甘,我有一些同学线上加线下实习后,在秋招面试中获得了喜人的成绩,而我因实习时间不太长,还在学习一些业务上的知识,导致没有准备错过秋招。
  3. 公司排期紧,首先导致加班严重,我没有时间自学其他方面知识,其次其他同事也因为排期很忙,导致有一些问题会一知半解或者随便找以前的业务代码来学习,往往在解决完问题后仍然一知半解,因为排期紧而又没有时间自己弄懂,不利于未来发展。

收获总结

  1. 熟悉了业务,懂得了前后端联调,和基本的接口请求等。
  2. 熟悉了antd方面关于表单后台的一些组件的使用。
  3. 学会了自学查看属性及其文档,

学习总结:

封装组件

在我原来的文章中要恋爱好歹开个小鹏吧中,就是运用react-router@6 版本来配置路由,用自己的代码没用组件来实现一个手机效果的分页切换路由的效果。而在实习期间,因为使用umi4,Umi4 使用 react-router@6 作为路由组件,并使用antd组件实现类似的效果。

image.png

配置前台门户路由

{
    path: '/portal',
    name: '门户',
    layout: false,
    routes: [
      {
        path: '/portal/home',
        name: 'test1111',
        icon: '',
        component: './LzjcPages/Portal/Home',
        // access: 'canNormalUser',
      },
      {
        path: '/portal/organization',
        name: 'test2222',
        icon: '',
        component: './LzjcPages/Portal/Organization',
        // access: 'canNormalUser',
      },
      {
        path: '/portal/learnCenter',
        name: 'test33333',
        icon: '',
        component: './LzjcPages/Portal/LearnCenter',
        // access: 'canNormalUser',
      },
      {
        path: '/portal/activeCenter',
        name: 'test44444',
        icon: '',
        component: './LzjcPages/Portal/ActiveCenter',
        // access: 'canNormalUser',
      },
      {
        path: '/portal',
        redirect: './LzjcPages/Portal/Home',
      },
    ],
  },

配置基本上同react-router@6,并且因为增加了权限控制access能够根据用户身份,来控制用户是否能够进入改页面。并且最后一个路由会一定匹配,因为与父路由一样,当其他子路由都没有匹配到的时候,直接跳转到首页。

封装公用组件HomeLayout

HomeLayout 是门户路由通用的组件,用来进行门户模块的切换时候的导航栏,在这里可以用来写一些通用的方法,例如登出、查询个人信息等,

const PortalLayout = (props) => {
    const { tabKey, children } = props;
    const [curTab, setCurTab] = useState('home');
    
    const [tabMenus, setTabMenus] = useState([  // 
        { title: 'test1', key: 'home' },
        { title: 'test2', key: 'organization' },
        { title: 'test3', key: 'learnCenter' },
        { title: 'test4', key: 'activeCenter' },
        { title: 'test5', key: 'checkCenter' },
    ]);


    useEffect(() => {   
        setCurTab(tabKey);
    }, [tabKey]);

    const switchTab = (key) => {
        if (key != 'courseDetailCenter' || checkLogin()) {
            setCurTab(key);
            history.push(`/portal/${key}`);
        }
    };
    
        const loginOut = async (currentUser) => {
        await outLogin();
        Cookies.remove('accessToken'); //删除存储
        const { origin, href } = window.location;
        let url = `${origin}${ORIGIN_BASE}/#${loginPath}?redirect=${href}&appCode=${APP_CODE}`;
        redirectLoginPath(url);
    };
    
       return (
        <div className={styles.proContainer}>
            <img className={styles.topImg} src={appImages.bgbanner} alt="" />
            <div className={styles.topToolBar}>
                <span className={styles.welcomeLine}>
                    欢迎来到党建工作{' '}
                    {formatTime({ type: 'yyyy-mm-dd', isweek: true })}
                </span>
                <span className={styles.enterBlock}>
                    <span onClick={() => { history.push('/index') }}>后台入口</span>
                    {/* <span>{currentUser && currentUser.user.userName}</span> */}
                    <span onClick={() => { loginOut() }}> 退出</span>
                </span>
            </div>
            <div className={styles.tabMenus}>
                <ul className={styles.nvaMenu}>
                    {tabMenus.map((d) => (
                        <li
                            className={`${styles.tabMenu} ${curTab == d.key && styles.tabMenuSelected}`}
                            key={d.key}
                            onClick={() => {
                                switchTab(d.key);
                            }}
                        >
                            <span>{d.title}</span>
                        </li>
                    ))}
                </ul>
            </div>

            <div className={styles.header}>  
                {children}   // 渲染子组件
            </div>
        </div>
    );

}

在上面代码中,封装了通用组件,来作为门户路由的通用组件,所有门户组件如首页都要引入改组件,作为导航栏,并且使用postion:stick 来使得导航栏一直出现在门户页面上。

    <PortalLayout tabKey="home">
            <div style={{display:"flex",justifyContent:"center",}}>
                <div  style={{fontWeight:"bold",fontSize:"40px"}}>test111111</div>
            </div>
    </PortalLayout>

StepsForm - 分步表单

实习目标效果如下:这里业务是一个复杂的流程表单,业务目标是在每个小流程中的下一步的时候,都要请求post 接口,保存当前小流程,并且当保存下一步后,不能退回进行修改了。当进入下一流程需要进行判断:如果以前进提交过大流程,只需要进入下一流程就可以。如果以前没有提交过大流程,则需要请求接口将整个大流程进行post接口提交。

image-20221122160916893.png

image-20221122161923471.png

定义主要变量:

current:表示当前处在哪个大流程

current1,current2,current3,current4,current5 分布控制处在大流程下的组件中所在小流程状况。

stepsKey 用来表示当前角色最高已经走到哪个大流程,因为我们能够返回上一流程,此时我们并不知道我们的大流程表单是否需要提交,若stepKey==current 当前流程,则表示当前走的流程是我们还未提交的,需要调用接口发送数据,如果stepKey > current,表示以前已经走过了,此时不需要调用接口,直接将current = current +1 ,通过current + 用户id + current1/2/3/4/5 来请求接口,拿到对应的数据。

代码实现:

    <StepsForm
                current={current}
                formMapRef={formRef}
                submitter={{
                    render: (props) => {
                        if (props.step > 0 && props.step <= 3) {
                            return [
                                <Button key="pre" onClick={() => {
                                    setCurrent(current - 1)
                                }}>
                                    上一流程
                                </Button>,

                                // {(current==1&&current1==2)}
                                ((current == 0 && current1 >= 2) || (current == 1 && current2 >= 4) || (current == 2 && current3 >= 5) || (current == 3 && current4 >= 7) || current == 4 && (current5 >= 7)) && <Button type="primary" key="goToTree" onClick={() => {
                                    formStep.validateFields().then((errors, values) => {
                                        props.onSubmit?.()
                                    }).catch((error) => { });

                                }}>
                                    下一流程
                                </Button>,

                            ];
                        }
                        if (props.step <= 3) {
                            return [
                                ((current == 0 && current1 == 2) || (current == 1 && current2 == 4) || (current == 2 && current3 == 5) || (current == 3 && current4 >= 7) || current == 4 && (current5 >= 7)) && <Button type="primary" key="goToTree" onClick={() => {
                                    formStep.validateFields().then((errors, values) => {
                                        props.onSubmit?.()
                                    }).catch((error) => { });
                                }}>
                                    下一流程
                                </Button>,
                            ]
                        }
                        if (props.step == 4) {
                            return [
                                <Button key="pre" onClick={() => {
                                    setCurrent(current - 1)
                                }}>
                                    上一流程
                                </Button>,
                                (current == 4 && (current5 >= 7)) && <Button type="primary" key="goToTree" onClick={() => {
                                    formStep.validateFields().then((errors, values) => {
                                        props.onSubmit?.()
                                    }).catch((error) => { });
                                }}>
                                    完成
                                </Button>,
                            ];
                        }

                    },
                }}
            >

                <StepsForm.StepForm name="step1" title="大流程1" className={styles.stepsleft} onFinish={(value) => {
                    if (current1 == 2) {
                        if (stepsKey == 0) {
                            handOneFinish()
                        } else {
                            setCurrent(current + 1)
                            setStepsKey(current + 1)
                        }

                    }
                }}>
                    {current == 0 &&
                        <PartyApply
                            dict={dict}
                            formRef={formStep}
                            activeKeyForm={activeKeyForm}
                            stepsKey={current}
                            initialValues={initialValues}
                            current={current1}
                            setCurrent={setCurrent1}
                            file={file}
                            setFile={setFile}
                            fileList={fileList}
                            setFileList={setFileList}
                            conversation={conversation}
                            setConversation={setConversation}
                            conversationList={conversationList}
                            setConversationList={setConversationList}
                            id={id}
                            setId={setId}
                        />
                    }
                </StepsForm.StepForm>



                <StepsForm.StepForm name="step2" title='大流程2' className={styles.stepsleft} onFinish={(value) => {
                    if (current2 == 4) {
                        if (stepsKey == 1) {
                            handTwoFinish()
                        } else {
                            setCurrent(current + 1)
                            setStepsKey(current + 1)
                        }

                    }
                }}>
                    {current == 1 &&
                        <PartyMember
                            dict={dict}
                            formRef={formStep}
                            activeKeyForm={activeKeyForm}
                            stepsKey={current}
                            initialValues={initialValues}
                            current={current2}
                            setCurrent={setCurrent2}
                            file={file}
                            setFile={setFile}
                            fileList={fileList}
                            setFileList={setFileList}
                            conversation={conversation}
                            setConversation={setConversation}
                            conversationList={conversationList}
                            setConversationList={setConversationList}
                            keep={keep}
                            keepList={keepList}
                            setKeep={setKeep}
                            setKeepList={setKeepList}
                            register={register}
                            registerList={registerList}
                            setRegister={setRegister}
                            setRegisterList={setRegisterList}
                            id={id}
                            setId={setId}

                        />
                    }
                </StepsForm.StepForm>



                <StepsForm.StepForm name="step3" title='大流程3' className={styles.stepsleft} onFinish={(value) => {
                    if (current3 == 5) {
                        if (stepsKey == 2) {
                            handThreeFinish()
                        } else {
                            setCurrent(current + 1)
                            setStepsKey(current + 1)
                        }
                    }
                }}>
                    {
                        current == 2 &&
                        <GrowTarget
                            formRef={formStep}
                            activeKeyForm={activeKeyForm}
                            dict={dict}
                            initialValues={initialValues}
                            current={current3}
                            setCurrent={setCurrent3}
                            stepsKey={current}
                            file={file}
                            setFile={setFile}
                            fileList={fileList}
                            setFileList={setFileList}
                            conversation={conversation}
                            setConversation={setConversation}
                            conversationList={conversationList}
                            setConversationList={setConversationList}
                            keep={keep}
                            keepList={keepList}
                            setKeep={setKeep}
                            setKeepList={setKeepList}
                            register={register}
                            registerList={registerList}
                            setRegister={setRegister}
                            setRegisterList={setRegisterList}
                            id={id}
                            setId={setId}
                        />
                    }
                </StepsForm.StepForm>




                <StepsForm.StepForm name="step4" title='大流程4' className={styles.stepsleft} onFinish={(value) => {
                    if (current4 == 7) {
                        if (stepsKey == 3) {
                            handFourFinish()
                        } else {
                            setCurrent(current + 1)
                            setStepsKey(current + 1)
                        }

                    }
    
                }}>
                    {
                        current == 3 &&
                        <PartyReceive
                            formRef={formStep}
                            activeKeyForm={activeKeyForm}
                            dict={dict}
                            initialValues={initialValues}
                            current={current4}
                            setCurrent={setCurrent4}
                            stepsKey={current}
                            file={file}
                            setFile={setFile}
                            fileList={fileList}
                            setFileList={setFileList}
                            conversation={conversation}
                            setConversation={setConversation}
                            conversationList={conversationList}
                            setConversationList={setConversationList}
                            keep={keep}
                            keepList={keepList}
                            setKeep={setKeep}
                            setKeepList={setKeepList}
                            register={register}
                            registerList={registerList}
                            setRegister={setRegister}
                            setRegisterList={setRegisterList}
                            wishBook={wishBook}
                            setWishBook={setWishBook}
                            wishBookList={wishBookList}
                            setWishBooksList={setWishBooksList}
                            opinion={opinion}
                            setOpinion={setOpinion}
                            opinionList={opinionList}
                            setOpinionList={setOpinionList}
                            id={id}
                            setId={setId}
                        />
                    }

                </StepsForm.StepForm>



                <StepsForm.StepForm name="step5" title='大流程5' className={styles.stepsleft} onFinish={(value) => {

                    if (current5 == 7) {
                        if (stepsKey == 4) {
                            handFiveFinish()
                        } else {
                            setVisible(false)
                            actionRef.current.reload();
                        }


                    }
                }}>
                    {
                        current == 4 &&
                        <PartyWorker
                            formRef={formStep}
                            activeKeyForm={activeKeyForm}
                            dict={dict}
                            initialValues={initialValues}
                            current={current5}
                            setCurrent={setCurrent5}
                            stepsKey={current}
                            file={file}
                            setFile={setFile}
                            fileList={fileList}
                            setFileList={setFileList}
                            keep={keep}
                            keepList={keepList}
                            setKeep={setKeep}
                            setKeepList={setKeepList}
                            register={register}
                            registerList={registerList}
                            setRegister={setRegister}
                            setRegisterList={setRegisterList}
                            wishBook={wishBook}
                            setWishBook={setWishBook}
                            wishBookList={wishBookList}
                            setWishBooksList={setWishBooksList}
                            opinion={opinion}
                            setOpinion={setOpinion}
                            opinionList={opinionList}
                            setOpinionList={setOpinionList}
                            id={id}
                            setId={setId}
                        />
                    }

                </StepsForm.StepForm>
            </StepsForm>
代码详情:
 首先拆分结构忽略功能, 我们最基本的代码结构是如下:下面代码就能够将大流程的流程图显示出来,通过current={current}来自动判断当前在哪个流程。
 <StepsForm
 	 current={current}
 	 submitter={...}
 >	
  <StepsForm.StepForm name="step5" title='大流程1' onFinish={()=>{}}>
    </StepsForm.StepForm>
    <StepsForm.StepForm name="step5" title='大流程2' onFinish={()=>{}}>
    </StepsForm.StepForm>
    <StepsForm.StepForm name="step5" title='大流程3' onFinish={()=>{}}>
   </StepsForm.StepForm>
   <StepsForm.StepForm name="step5" title='大流程4' onFinish={()=>{}}>
   </StepsForm.StepForm>
   <StepsForm.StepForm name="step5" title='大流程5' onFinish={()=>{}}>
   </StepsForm.StepForm>
 </StepsForm>
 
 ==============================================
  其次通过current 当前流程,来调用该流程对应的组件,该组件控制的是小流程的显示,通过传入currentn, 进行小流程控制
  { current == n && <SomeComponent/>} 
// 下面写一个大流程1对应的组件
const StepsProces = (props) => {
    const { formRef, stepsKey, dict, activeKeyForm, initialValues, current, setCurrent, file, setFile, fileList, setFileList, conversation, setConversation, conversationList, setConversationList, id, setId, ...propsI } = props;
    const actionRef = useRef();
    const [validator, setValidator] = useState([]);
    const validatorData = validator ? validatorObj(validator) : {};
    const accessToken = Cookies.get('accessToken') || ''; //token

    //form回显
    useEffect(() => {
		.... // 表单数据回显
    }, [])


    const stepsForm1 = (<div>
        <Form form={formRef} action={actionRef} layout="vertical" >
            <Row gutter={24}>
                <Col span={8}>
                    <Form.Item name="sqrdzz" label="吃饭" rules={formItemValidator(validatorData.sqrdzz)}>
                        <TreeSelect
                            treeData={handleData(
                                dict?.treeData,
                                { nodeName: 'name', nodeId: 'id', children: 'children' },
                                'treeSelect',
                            )}
                            showCheckedStrategy={TreeSelect.SHOW_ALL}
                            placeholder="吃饭"
                            treeDefaultExpandAll
                            disabled={current == 2 || activeKeyForm > 1}
                        />
                    </Form.Item>
                </Col>
                <Col span={8}>
                    <Form.Item name="sqrdsj" label="睡觉" rules={formItemValidator(validatorData.sqrdsj)}>
                        <DatePicker placeholder='睡觉' disabled={current == 2 || activeKeyForm > 1} />
                    </Form.Item>
                </Col>

            </Row>
        </Form>
    </div >)

    const stepsForm2 = current > 1 && (<div>
        <Form form={formRef} layout="vertical">
            <Row gutter={24}>
                <Col span={8}>
                    <Form.Item name="thr" label="多读书" rules={formItemValidator(validatorData.thr)}>
                        <Select placeholder="多读书" disabled={activeKeyForm > 1} showSearch filterOption={(input, option) =>
                            option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
                        }>
                            {dict.dyryxx &&
                                dict.dyryxx.map((item, index) => (
                                    <Option value={item.id} key={index}>
                                        {item.xm}
                                    </Option>
                                ))}
                        </Select>
                    </Form.Item>
                </Col>

                <Col span={8}>
                    <Form.Item name="thsj" label="多看报" rules={formItemValidator(validatorData.thsj)}>
                        <DatePicker placeholder='多看报' disabled={activeKeyForm > 1} />
                    </Form.Item>
                </Col>
               
            </Row>
        </Form>
    </div>)

 // 请求下一步的接口,对当前小流程进行保存
    const handleNext = () => {
		.......
    }

    return (
        stepsKey == 0 &&
        <div className={styles.stepsInfo}>
            <Steps progressDot direction="vertical" current={current} initial={1} className={styles.stepsInfoHeader}>
                <Step key={1} title={"小流程1111"} description={stepsForm1} />
                <Step key={2} title={"小流程2222"} description={current > 1 && stepsForm2} />
            </Steps>

            <div className="steps-action">
                {current < 2 && (
                    <Button type="primary" onClick={() => { handleNext() }}>
                        下一步
                    </Button>
                )}
            </div>
        </div>
    );
};

代码解释:
 小流程需要用到antd的Steps的步骤条,也跟StepsForm 类似,有总Steps 和 分 StepStep 的每一个description 都表示一个Form表单,表达的就是小流程,有完整的表单事件。然后当点击下一步,会将当前处在的流程进行上传接口,进入下一个小流程。

Echars 图

Echars 图在实现前我也接触过,在实习中也用到了,复习了一遍还是很不错的,其中主要难点都在配置项的一些繁琐配置中,在开发的过程中,经常都是去Examples 例子中,找到相似的在此基础上进行修改,常常会遗漏某些配置项的属性的意义,在总结中也给我了复习的机会,重新全面了解这些配置项。

例如:以玫瑰图为例子,列举其详细属性

image-20221123090915613.png


// 玫瑰图设置
const Echars2 = (props) => {
 const { id } = { ...props }   // 通过透传获取id,该id用于请求接口,获取某个id下的数据项
 let option = {     // 配置项
     legend: {     // 图例组件。 图例组件展现了不同系列的标记(symbol),颜色和名字。可以通过点击图例控制哪些系列不显示
         top: '15%', // 图例组件离容器上侧的距离,可以是百分比,也可以是像素,也可以是单词如:middle,top,bottom
         width: "20%", // 图例的宽度,当orient设置为vertical,就是每一行一个图例,设置horizontal只有一行排满才会换行
         right: "5%",  // 距离右边的距离 top,width,right,left 不给值默认都是auto
         orient:"vertical", // 设置排列为竖向排列,默认设置为"horizontal",横向排列
         // type :'plain':普通图例。缺省就是普通图例。 /  'scroll':可滚动翻页的图例。当图例数量较多时可以使用。
         // tooltip   在legend 中也有tooltip,表示的是鼠标悬浮图例显示提醒,也有formatter,返回标签显示效果	
         // formatter: function (name) {
         //    return echarts.format.truncateText(name, 40, '14px Microsoft Yahei', '…'); //name:数据, 40宽度, 14px.. 字体
         //  },
     },
     tooltip: {  
         trigger: 'item',
         formatter: function (params) {
             return `<span>${params.name}</span></br><span style="color:#5470C6">${params.data.value}(${params.percent}%)</span>`
         },
         borderColor: "#f2f3f5",
     },
     toolbox: {
         show: true,
     },
     series: [
         {
             name: '暂无',
             type: 'pie',
             radius: [20, 80],
             center: ['35%', '50%'],
             roseType: 'area',
             // itemStyle: {
             //     borderRadius: 5
             // },
             label: {
                 show: false
             },
             data: []
         }
     ]
 };

 const initChart = () => {
     let element = document.getElementById('chart2');
     let myChart = echarts.init(element);
     myChart.clear()
     myChart.setOption(option);

 }

 const ageSwitch = (num) => {
     switch (parseInt(num)) {
         case 1:
             return '28岁以下'
         case 2:
             return '29-35岁'
         case 3:
             return '36-50岁'
         case 4:
             return '51-60岁'
         case 5:
             return '61岁以上'
     }
 }

 useEffect(async () => {
     const resp = await getNlfbTj({ unitId: id })
     if (resp.code == 200) {
         let list = []
         resp.result.map(v => {
             list.push({ value: v.sl, name: ageSwitch(v.zd) })
         })
         console.log(list)
         option.series[0].data = list
         initChart()

     } else {
         message.error(resp.message)
     }
 }, [id])

 return (
     <>
         <div style={{ display: "flex", justifyContent: "flex-start", height: "15%" }}>
             <div className={styles.echars1}>
                 <div className={styles.image}></div>
                 <div className={styles.text}>党员年龄分布</div>
             </div>
         </div>
         {
             <div id='chart2' style={{ width: '100%', margin: '14px auto 0px', height: '85%', marginTop: 6 }}>

             </div>

             // <div className={styles.brithEmpty}><img src={appImages.empty} /></div>
         }

     </>
 )
}

export default Echars2;

各种配置项介绍

option:设置配置项

legend:

图例组件。 图例组件展现了不同系列的标记(symbol),颜色和名字。可以通过点击图例控制哪些系列不显示

legend.top 图例组件离容器上侧的距离,可以是百分比,也可以是像素,还可以是单词:middle,top,bottom

legend.bottom 图例组件离容器下侧的距离,可以是百分比,也可以是像素

legend.left/ legend.right 图例组件离容器左/右侧的距离,可以是百分比,也可以是像素 。

上面四个属性代表图例在容器中的位置,默认值是auto

legend.orient 图例组件的排列方式,是水平排列还是竖直排列,默认值为'horizontal'水平排列。'vertical'垂直排列需手动设置

legend.width/ height

图例组件的宽高,可以是百分比,也可以是像素 。 当图例组件设置水平排列,当width不够放下一个图例的Item的时候,就会在下一行重新进行水平排列,同理垂直排列类似,当高度不够下一个图例的Item的时候,改变width,移动继续垂直排列。

legend.type

'plain' : 普通图例,当width和height 都不够的时候,会发生缺省,就是普通实例

'scroll': 当宽和高都不够,也就是图例数量较多时,可滚动翻页的图例,需要详细配置

legend.tooltip 设置悬浮于某个图例的弹窗提醒,跟option.tooltip类似,在后面详细介绍

legend.formatter 制定悬浮框的某些样式,提示框浮层内容格式器,支持字符串模板和回调函数两种形式。

剩下的一些属性比较杂,不常用,多是Item图例的详细设置,就不多介绍了。

tooltip:

提示框组件的通用介绍:

提示框组件可以设置在多种地方:

  • 可以设置在全局,即 tooltip
  • 可以设置在坐标系中,即 grid.tooltip、polar.tooltip、single.tooltip
  • 可以设置在系列中,即 series.tooltip
  • 可以设置在系列的每个数据项中,即 series.data.tooltip
  • 可以设置在图例中,即legend.tooltip

tooltip.trigger

触发类型,默认为 tooltip.trigger= 'item'

'item' : 数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用

'axis' : 坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用。

'none': 什么都不触发。

tooltip.formatter

提示框浮层内容格式器,支持字符串模板和回调函数两种形式:

支持字符串模板

模板变量有 {a}, {b}{c}{d}{e},分别表示系列名,数据名,数据值等。 在tigger为 'axis' 的时候,会有多个系列的数据,此时可以通过 {a0}, {a1}, {a2} 这种后面加索引的方式表示系列的索引。 不同图表类型下的 {a}{b}{c}{d} 含义不一样。 其中变量{a}, {b}, {c}, {d}在不同图表类型下代表数据含义为:

  • 折线(区域)图、柱状(条形)图、K线图 : {a}(系列名称),{b}(类目值),{c}(数值), {d}(无)
  • 散点图(气泡)图 : {a}(系列名称),{b}(数据名称),{c}(数值数组), {d}(无)
  • 地图 : {a}(系列名称),{b}(区域名称),{c}(合并数值), {d}(无)
  • 饼图、仪表盘、漏斗图: {a}(系列名称),{b}(数据项名称),{c}(数值), {d}(百分比)

回调函数

formatter: function (params) {
                return `<span>${params.name}</span></br><span style="color:#5470C6">${params.data.value}                                    (${params.percent}%)</span>`
            },

其中 params.name 代替的是饼图的 {a}, params.data.value 代表 {c}, params.percent 代表{d},这些只需要打印出来就可以了。

回调函数比字符串模板相比,有一些优势,比如更加灵活,比如出现了在一个弹窗中的字符串中,得出现俩个不同颜色的,如上面的例子,这里使用模板字符串,使用统一的 tooltip.textStyle.color 的话会全部修改其颜色,因此最好的方法是通过回调函数,返回Html字符串,通过Html中的style 来设置特定某些文字的颜色。

tooltip.borderColor 提示框浮层的边框颜色。

tooltip.textStyle 提示框浮层的文本样式。拥有包括color,fontStyle,fontWeight,fontFamily,fontSize 等等属性。