micherwa

micherwa 查看完整档案

上海编辑  |  填写毕业院校莉莉丝游戏  |  前端负责人 编辑 github.com/micherwa 编辑
编辑

朋友都叫我超哥,专注前端开发8年。
目前在知名游戏公司的广告技术中心担任前端负责人。

欢迎关注我的公众号 “超哥前端小栈”,交流更多的想法与技术。

个人动态

micherwa 赞了文章 · 2020-12-12

javascript高级程序设计(第四版)中文

链接: https://pan.baidu.com/s/1EzmH... 密码: b7j1
中文高清版,谢谢打赏
image

查看原文

赞 18 收藏 1 评论 2

micherwa 回答了问题 · 2020-03-04

解决element upload 报错Cannot set property 'status' of null

每次在文件成功上传后的 on-success 回调里,用 setTimeout 的确可以解决报错问题。

主要是因为自定义了 file-list

关注 3 回答 3

micherwa 回答了问题 · 2020-01-13

safari浏览器下有没有单独的CSS hack?

举个例子,在 chrome(version:79.0.3945.117) 中,下面这段样式可以生效(scss 预编译)。

div {
    span {
        padding-left: 10px;
    }
}

但在 safari (version: 13.0.4)中,却发生了偏移。这时,可以用下方的 hack 写法进行微调修正:


div {
    span {
        padding-left: 10px;
    }

    @media not all and (min-resolution:.001dpcm) {
        span {
            padding-left: 6px;
        }
    }
}

亲测可用。

关注 5 回答 4

micherwa 发布了文章 · 2019-12-27

超哥的2019年度总结

bg-20191222-01.jpg

仿佛是眨眼间,就到了 2019 年的末尾。回想这一年,可以用 “忙” 这个词来概括,故记录下这篇年度总结留作回顾,并在此与大家分享。

写作

今年年初开了个人公众号 「超哥前端小栈」,旨在聊聊技术、面试,聊聊前端人的成长,并希望成为你的陪伴者。至今共输出近 30 篇原创文章,同步更新于 掘金segmentFaultgithub、微博 等地带。

写作的初衷,一方面是为了沉淀自己的技术,另一方面是为了能修正自己对某一块知识点理解不到位的地方。因为在决定写某一篇文章之前,我还并不懂,通过写作,将自己对某一知识点的理解表述出来,我也逐渐地明白了一些,我很享受这一过程。在这期间,也结识了一些大佬,获得了更多技术上的交流,可谓收获颇丰。

我将写过的文章分为了几类,具体列表如下:

面试系列

干货系列

源码系列

个人感悟

学习

今年的书籍读得更多了。技术类的如《React 状态管理与同构实战》、《JavaScript框架设计(第二版)》等,管理类有的《能力陷阱》、《任正非管理思想》,励志与成功类像的《关键对话》、《刻意练习》等,还有恐怖悬疑类小说的《猎罪师》、《无罪谋杀》等等。

其中,我想与大家分享的是,《JavaScript框架设计(第二版)》一书中,关于如何选书去学习的观点。我摘录并概括了其中的一些看法:

为了有效地快速学习、效仿的方法,是多看几本进阶的书。有人说,书买十本看一本也是值的,我觉得有待商榷。个人推荐钱穆的另一个说法。当年,李敖想它请教治学的方法,他回答说:

并没有具体的方法,要多读书、多求解,当以古书原文为底子、为主,免受他人成见的束缚。书要看第一流的,一遍一遍读。与其十本书读一遍,不如一本书读十遍。不要怕大部头的书,养成读大部头书的习惯,则普通书就不怕了。

从中得到的启示有以下几点:

  • 1、读好书。前端的好书也有不少,如红皮书、犀牛书、蝴蝶书、乌龟书、时钟书、鸽子书。。。《你不知道的JavaScript》也很有特色。
  • 2、读原版。在 IT 行业,特指英文原版。大凡新技术出来,几乎都是以英文为载体出现的,然后时隔一年半载,才翻译到国内,所以学习新技术还是要看原版英文书。
  • 3、精读,就是反复看。多看书是一定的,但如果发现树上说的东西你始终看不进去时,一定不要坚持,一般来说看不下去的原因是:要么你还没达到看本书的水平,不适合你看;要么就是它的确是本“烂书”,遇到这种情况,赶紧换书。如果遇到一本适合自己的书,一定要坚持看下去,看到不懂的东西多搜索,搜索不到就多问人。
  • 4、看厚书。一些集大成者的书,比如在 JavaScript 领域,所谓的大部头的书莫过于《JavaScript权威指南》等。厚达千页,很多细节都涉及到了。
每个时代对框架的需求都不一样。引用《从 0 到 1》里的话——商业界的每一刻都不会重演。下一个比尔盖茨不会再开发操作系统,下一个拉里佩奇,或是谢尔盖布林不会再研发搜索引擎,下一个马克扎克尔伯格也不会去创建社交网络。如果你照搬这些人的做法,你就不是向他们学习了。

此外,掘金,segmentFault,CSDN 等论坛每天在上班前,都会逛一圈。

各类公众号的文章,也几乎每天都有拜读。比如,《湖畔大学梁宁:比能力重要1000倍的,是你的底层操作系统》,《玉伯:我的前端成长之路》等好文,不断地开阔着我的眼界,增长着我的见识。

活到老,学到老 ~ 新的一年,将会继续鞭策自己,坚守信念,不断学习。

分享会

游戏公司的前端,大多被分散在各个项目组里,平时沟通交流的机会也不多。为了让大家能有更多的交流与沟通,我主动牵头发起了 “前端分享会” 活动。

考虑到大家的忙碌程度,每三周会组织一次 时长在 1 小时以内的技术分享。分享会的主题,与实际工作紧密相连,比如《前端工程代码规范》、《用 Vue + Echarts 打造你的专属可视化界面》、《React 组件进阶设计模式》等等。

几次分享会之后,大家都表示很有收获。对于分享的态度,也变得越来越积极,有同学还会在本次分享的结尾,提前预定下一次分享的主题,并说已经在准备了。整个分享的氛围,已渐入佳境。

其实,分享会的最大收益者,是分享者本人。在有限的时间内,要把自己要说的知识点讲明白,这非常考验人的表达能力,对知识点的理解能力,以及整个分享过程的节奏把控能力等等,这是很能锻炼人的。

“前端分享会” 这一活动的开展,得到了老板们的赞赏与支持。新的一年,我会继续坚持地做下去。

工作

今年 10 月,由公司发行的游戏《万国觉醒》,在海外首次登顶 “收入榜首”,作为公司的一员,着实小膨胀了一把 ~

bg-20191222-02.jpg

我主要负责广告系统的相关工作,希望能把它做得更大更强。期待我们的产品,在国内也能起飞 ~

所以,最近一个月,真的是异常地忙碌。同事调侃我是 “铁人”,说我每天过着 8-11-7 的日子(后来细想,其实也没那么夸张。但每天早上 9 点前,肯定是能在工位上看到我的。那一个月只休了 2 天,倒是真的)。另一件事是关于身边的小伙伴的,他某天晚上 10 点半到家,舍友开玩笑地打招呼道:好久不见(他们是真的一个月没见面了,因为那段时间 12 点后下班也是常事)。

我印象最深的一次,凌晨3点半回到家,一番洗漱后,感觉才躺下没多久,就被 3 岁多的女儿摇醒:“爸爸,我要起床啦 ~ ” 睁眼一看,06 点 02 分 !?!

好吧,新的一天又开始了。深吸一口凉凉的空气,开始起身,给女儿穿衣,哄着洗漱,吃早饭,再帮她梳妆打扮。间隙间,才顺便搞定了自己。然后出门,送她去幼儿园。等我上了地跌,靠在门边时,才长长地喘了一口气。

下午开完 1 个多小时的项目评审会后,感觉整个人都在飘了。回到工位后,分配好任务,继续干活,直到晚上11点。坐在回去的出租车上,我竟然睡着了。。。

如此,竟然就这么度过了那一个月。感谢上苍,活着真好~ 也庆幸自己过去一直长期地健身,不然还真可能在某天看到: “据报道 XX 程序员猝死” 的新闻了(开个玩笑 ^ _ ^)。

运动

关于健身,是我时常挂在嘴边的一个话题。不仅仅是爱好,更是希望警醒自己:随着年岁的增长,身体素质是我时刻都要关注的事情!

今年年初给自己定了个小目标:坚持每周健身 4 次,引体向上单组数量突破 20 个。

只能说勉强达成了吧。工作日每周中午一般会去 4-5 次,有时晚上还会去打 2 小时羽毛球。引体向上的最新数据为:19.5个/组,第 20 个还差那么一点,但对于目前的我来说真的有点难了。新的一年,还要继续努力~

无论工作多么繁忙,健身是我会一直坚持下去的事情,不仅仅是爱好而已。如果我们无力改变大环境,那就选择改变自己吧。

生活

今年,在生活上,让我感受最大的变化是,女儿越来越懂事了。

没有了过去莫名的吵闹,虽然有时候也会因为没有及时地满足她而不开心,但已经可以通过一番耐心的交流,逐渐地缓和情绪,甚至破涕为笑。

她会在大人忙碌家务的时候,自己一个人乖乖地玩玩具,直到她发现我们空下来了,才会喊上我们陪她一起玩。

她会在我下班回到家的那一刻,颇为兴奋地喊一声:爸爸!并在第一时间冲过来给我一个大大地拥抱,然后帮我拿出拖鞋,还非要帮我换上后,才肯回去继续玩她的玩具。有时,甚至会挂在我小腿上紧紧抱住耍赖不肯下来,当我走路时,她会随着我的摆动,笑得不亦乐乎。

有时候,她会拿着卡片来考我英文单词:“爸爸,你知道这个(河马)英文怎么读嘛?” 看着我一脸懵逼,她会歪着脑袋,得意地说:你跟我念哟,Hippopotamus(读:ˌhɪpəˈpɒtəməs)。我本想着蒙混过关,就含糊地念了一遍,不成想还被她纠正说发音不对,再来一遍。直到我念对了,她才说道:“爸爸,回去以后,你要多念哦,然后你就会了,你要加油哟!好了,今天的课就上到这里,下课!” 然后,就蹦蹦跳跳地跑开了。只剩我一人,在那儿“凌乱”,心想:这小词一套一套的,她从哪儿学的?

有时候,她会玩着玩具,突然 “诗兴大发”地开始背唐诗。“李白乘舟将欲行,忽闻岸上踏歌声。” “两只黄鹂鸣翠柳,一行白鹭上青天。” 然后,猛地转头问我:爸爸,接下去是什么?我:“。。。什么。。。船。。。” 她则表现出一副认真的表情,说道:“窗含西岭千秋雪,门泊东吴万里船。” 然后眉头一挑:“爸爸,怎么这都不知道呀?来,你跟着我读一遍” 我:“。。。。。。”

我知道,女儿的这些变化背后,是老婆默默地付出。

自己带娃,自己教,是很累的。每天晚上,除了睡前故事,老婆还要教女儿认识英文单词,背诵古诗词,甚至,像《笠翁对韵》这样的古风曲子,女儿已经能唱得有模有样了,真的很辛苦。所以在我休息的时候,会给老婆 “放假”,让她出去逛街也好,练瑜伽也行,我在家带娃。

夫妻之道,本就需要相互理解,相互扶持,相互付出。前两天看到这样一段话,挺有感触的,分享给大家:

有些道理,要生了孩子以后才知道,三流的爱情是他给你买包,二流的爱情是相伴到老,而一流的爱情,是往后余生,儿子的功课由我辅导。

面向 2020

说一些期许吧。

希望自己能继续保持不断学习的状态。希望每周的健身频率,保持不变,坚持下去。希望家人都能身体健康,女儿快乐成长。

公众号我会继续写下去,希望每一位读者,都能从文中获得些许收获。如果你觉得还不错,请前往 github 轻点一下 star ~ 大家的赞,将是我一直写下去的动力,感谢支持!

PS:欢迎关注我的公众号 “超哥前端小栈”,交流更多的想法与技术。

本文参与了SegmentFault思否征文「2019 总结」,欢迎正在阅读的你也加入。
查看原文

赞 13 收藏 6 评论 4

micherwa 赞了文章 · 2019-12-18

前端解决第三方图片防盗链的办法 - html referrer 访问图片资源403问题

图片描述

问题

笔者网站的图片都是上传到第三方网站上的,比如 简书、掘金、七牛云上的,但是最近简书和掘金都开启了 防盗链,防止其他网站访问他们网站上的图片了,导致笔者的网站存在他们网站上的图片全挂了。

具体问题,就是 html 中通过 img 标签引入一个第三方的图片地址,报 403 。但是这个图片地址直接复制出来在地址栏打开,却是看得到的。

原因

官方输出图片的时候,判断了来源 Referer ,就是从哪个网站访问这个图片,如果是你的网站去加载这个图片,那么 Referer 就是:你的网站地址;

如果我们的网站地址不在官方的白名单内,所以就看不到图片了。

我们做这个跳板的关键:不发送 Referer,也就是没有来源。那么官方那边,就认为是从浏览器直接访问的,所以就能加载正常的图片了。

解决方案

如原网址:

http://mmbiz.qpic.cn/mmbiz/DU...

显示此图片来自微信公众平台,未经允许不得应用

方法:在 <head> 标签里加 meta

<meta name="referrer" content="never">

这样存在第三方网站上的图片,在你的网站上就可以访问了。

referrer

在某些情况下,出于一些原因,网站想要控制页面发送给 server 的 referrer 信息的情况下,可以使用这一 referer metadata 参数。

参数

referer 的 metedata 属性可设置 content 属性值为以下集合:

  • never
  • always
  • origin

结果

  • 如果 referer-policy 的值为 never:删除 http head 中的 referer;
  • 如果 referer-policy 的值为 default:如果当前页面使用的是 https 协议,而正要加载资源使用的是普通的 http 协议,则将 http header 中额 referer 置为空;
  • 如果 referer-policy 的值 origin:只发送 origin 部分;
  • 如果 referer-policy 的值为 always:不改变 http header 中的 referer 的值;

举例

如果页面中包含了如下 meta 标签,所有从当前页面中发起的请求将不会携带 referer:

<meta name="referrer" content="never">

如果页面中包含了如下 meta 标签,则从当前页面中发起的 http 请求将只携带 origin 部分:

<meta name="referrer" content="origin">

最后

博客首更地址 :https://github.com/biaochenxuying/blog

往期精文

尤雨溪 6 月 4 日的 Vue 技术分享

[今天尤雨溪公布Vue 3.0重大变化! 前端框架将何去何从?[附完整PPT]](https://mp.weixin.qq.com/s/fL...

十分钟弄懂:数据结构与算法之美 - 时间和空间复杂度

一张思维导图辅助你深入了解 Vue | Vue-Router | Vuex 源码架构

Vue + TypeScript + Element 项目实战及踩坑记

vue-cli3.x 新特性及踩坑记

那些必会用到的 ES6 精粹

参考文章:

  1. 微信图片防盗链解决办法
  2. Meta referrer标签的简要介绍

欢迎关注以下公众号 全栈修炼,学到不一样的武功秘籍 !

关注公众号并回复 福利 可领取免费学习资料,福利详情请猛戳: 免费资源获取--Python、Java、Linux、Go、node、vue、react、javaScript

全栈修炼

查看原文

赞 19 收藏 12 评论 0

micherwa 回答了问题 · 2019-11-14

求路过前辈留下宝贵建议

现在的市场行情,对新人可能不够友好,身边也有一些写了几年代码的朋友没找到工作。

但换一个角度想:正因为你年轻,有大把的时间可以去学习。

不要因噎废食,现在找不到好的工作,并不代表前端这条路就走不下去了,每个人的第一份工作是至关重要的,很多人可能这一辈子做的,都是跟第一份工作相关的工作。

好好想想吧,当初决定走前端这条路的初衷。无论今后想做什么,切记一定要做好规划,肯吃苦,好好积累,才会慢慢变好。

关注 5 回答 5

micherwa 回答了问题 · 2019-11-06

解决微信浏览器打开链接出现白屏,怎么解决?

估计是 # 的问题。

把路由的 hash 模式改为 history 试试,记得要配置服务器,具体怎么配 vue-router 文档里有

关注 6 回答 5

micherwa 回答了问题 · 2019-11-06

解决postman给node服务发post请求正常, 我的react项目发post请求就一直是pending状态,各位大佬请赐教

你的 2 个 protocal 不一样,一个5000,一个3000。

不知道你是否还做了跨域处理

关注 4 回答 4

micherwa 发布了文章 · 2019-10-31

「干货」用 Vue + Echarts 打造你的专属可视化界面(下)

前言

接上一篇文章 《「干货」用 Vue + Echarts 打造你的专属可视化界面(上)》),今天着重介绍 标记 的用法,来实现下图中的效果。

所用的 Echarts 的版本号为: v4.3。v-charts 的版本号为:v1.19.0。

标记的用法有很多,今天要介绍的场景有:折线图、柱状图、折线图 + 柱状图。

折线图标记 —— symbol

上图中,折线的拐点处,一些 “小圆点”,被替换成了小图标。

要实现这样的效果,需要先理一下原始的需求:

  • 每种标记,代表一种活动类型。
  • 有一些活动会发生在某些时间点,或时间段内,需要在活动发生的日期上标注出该活动的类型。
  • 当同一天有多个活动发生时,采用复合图标,并当展示 tooltip 时,显示当日的每一个活动的信息。
  • tooltip的布局为:首先显示当前日期,中段展示各个活动的图标以及活动名称,最后展示指标名称和对应的数值。
  • 没有活动的日期,拐点处与 tooltip 照常显示原先的样式。

所以,它的完整效果,应该是这样的:

要实现这样的效果,需要思考以下几点:

  • 如何通过日期的定向匹配,将活动的图标以“打点”的形式,定在折线拐点处。
  • 图标的大小,要怎么设置?它需要区别于正常的拐点标识。
  • tooltip 的样式要如何改写?还需要兼容没有活动的日期样式。

思路解析:

首先,为了做日期的定向匹配,需要设计的数据结构如下:

data: [
    {
        id: '1, 1, 3, 2',
        date: '2019-10-10',
        name: 'test-name1, test-name2, test-name3, test-name4'
    },
    ...
]

接下来的这个 核心 属性:symbol 是关键,它其实就是折线上的 拐点

symbol 支持的标记类型有:circle、rect、roundRect、triangle、diamond、pin、arrow、none。默认情况下为 emptyCircle,也就是空心的圆。

它还支持链接的格式:'image://http://xxx.xxx.xxx/a/b.png'。此外,如果需要每个数据的图形不一样,可以设置为如下格式的回调函数:

(value: Array|number, params: Object) => string

其中第一个参数 value 为 data 中的数据值。第二个参数 params 是其它的数据项参数。

这些正是我们需要的。踩坑亲测:上述回调函数,只有在最新版的 V4.3 中才能正常使用,否则会报错。这也是为何,我在一开始就先强调了 Echarts 的版本问题。具体实现如下:

<ve-line ... :extend="chartExtend"></ve-line>
...

// mock 包含标注的数据结构
dataList: [
    {
        id: '1, 1, 3, 2',
        date: '2019-10-10',
        name: 'test-name1, test-name2, test-name3, test-name4'
    },
    ...
    {
        id: '1',
        date: '2019-10-17',
        name: 'test-name1'
    }
],
...

setChartExtend () {
    this.chartExtend = {
        series: (v) => {
            Array.from(v).forEach((e, idx) => {
                e.symbol = (value, params) => {
                    return getSymbolIcon(params.name, dataList);
                };
                e.symbolSize = (value, params) => {
                    return getSymbolSize(params.name, dataList);
                };
            });
            return v;
        },
        ...
    };
},

getSymbolIcon (date, dataList) {
    const defaultSymbol = 'circle';

    if (!dataList || dataList.length === 0) {
        return defaultSymbol;
    }

    // 通过日期匹配,找到对应的标注对象
    const dataItem = dataList.find(item => item.date === date);

    const iconUrl = getSymbolUrl(dataItem.id);
    return iconUrl ? iconUrl : defaultSymbol;
},

getSymbolSize (date, dataList) {
    if (!dataList || dataList.length === 0) {
        return 4;
    }

    // 通过日期匹配,找到对应的标注对象
    const dataItem = dataList.find(item => item.date === date);

    return dataItem ? 15 : 4;
},

getSymbolUrl (id) {
    // 这里需要额外先做一层准备工作:将图标按 id 对应图标进行命名,然后传到自家的cdn上
    // 命名可以像这样:symbol-icon-1.jpg、symbol-icon-2.jpg 等等
    // 这里拿到标注的id,拼上链接返回即可
    // 形如:image://http://xxx.xxx.com/symbol-icon-1.jpg
    // 遇到多个 id 的情况,可以多加一个复合图标来处理,id 可以定为 0
}

最后的一个问题,如何改写 tooltip 的样式问题,以做好兼容呢?

之前说到,tooltip 的布局分为三块:日期、标注信息、具体数值。那么我们就以此,来重新绘制 tooltip。

tooltip 支持 formatter 回调函数,它的返回值类型是 Sting。

// 回调函数格式
(params: Object|Array, ticket: string, callback: (ticket: string, html: string)) => string

日期的信息,可以通过 params[0].axisValue 来获取。

获取标注信息的方法,与上述获取图标的思路类似,只是这里需要展示具体的标注类型和名称。

具体的数值,可以通过 params 中的 marker,seriesName,value 等属性获得。具体实现如下:

setChartExtend () {
    this.chartExtend = {
        series: (v) => {
            ...
        },
        tooltip: {
            formatter: (params) => {
                return getTooltipResult(params, dataList);
            }
        }
    };
},

getTooltipResult (params, dataList) {
    const dateResult = params[0].axisValue;
    // 获取原版 tooltip 的渲染结构
    const originalResultObj = getOriginalTooltipResult(params);

    if (!dataList || dataList.length === 0) {
        return dateResult + originalResultObj.strResult;
    }

    const dataItem = dataList.find(item => item.date === date);

    if (dataItem) {
        return dateResult +  getSymbolResult(dataItem, originalResultObj.strResult);
    }

    return dateResult + originalResultObj.strResult;
},

getOriginalTooltipResult (params) {
    let result = '';

    params.forEach((param, idx) => {
        // value 会因为 seriesType 的不同,类型也会有不同
        let value = Object.prototype.toString.call(param.value) === '[object Array]' ? param.value[1] : param.value;

        const str = `${param.marker}${param.seriesName}: ${ value }<br>`;
        result += str;
    });

    return {
        strResult: result
    };
},

getSymbolResult (dataItem, originalResult) {
    // 将 dataItem 的 id 转为数组的形式,循环渲染输出图标与名称的组合
    const dataIds = dataItem.id.split(',');
    const dataNames = dataItem.name.split(',');

    dataIds.forEach ((id, idx) => {
        // 通过 id 换取 图标的链接
        const iconUrl = ...;

        // 仿照 param.marker 的 style 写法,渲染图标样式
        const str = `<img data-original="${iconUrl}" width="11" height="11" style="display: inline-block; margin-right: 4px; margin-left: -1px;">${dataNames[idx]}<br>`;

        result += str;
    });

    return result + originalResult;
}

或许有同学会问 getOriginalTooltipResult 方法返回的值,里面只有一个 strResult,为何要设计为对象?

其实是为了方便扩展。例如,可以在日期的后面跟上下方具体数据的值的总计。那就需要通过 getOriginalTooltipResult 方法里的 params 循环,计算出 total,在配合上样式,生成一个 strTotal。

getOriginalTooltipResult (params) {
    ...

    return {
        strTotal: strTotal,
        strResult: result
    };
}

此外,在实际的业务中,还可能会出现某些线的数值是百分比。那就需要再对 getOriginalTooltipResult 方法做扩展,比如传入一个 options 对象:

getOriginalTooltipResult = (params, options = { isLinePercent: false, isShowTotal: false }) {
    ...
}

至此,折线图标记的渲染,就能完美地呈现了。

柱状图标记 —— markPoint

很尴尬的一点是:柱状图没有 symbol 属性。也就意味着上面的折线图的那一套,在柱状图中玩不转了。

没办法,只能从头查文档,继续找资料。经过一番“摸爬滚打”,终于发现了 markPoint 这个属性。在 markPoint 这个对象里面,可以设置 symbol,这样的话,那么之前搞出来的那一套就没有白费呀?!?

需要注意的是,markPoint 的默认 symbol 为 'pin',就是一个气泡的图标。另外,想要让 markPoint 的标记出现,就必须设置它的 data 属性。我们需要设置 data 里的这样几个属性:

data: [
    {
        symbol: '...', // 设置标记的图标链接
        symbolSize: 15, // 设置标记的大小
        coord: [index, 0], // x 轴的第 index 个上,打标记
        symbolOffset: [0, 0] // 将标记定位在 x 轴上
    },
    ...
]

具体的实现代码如下:

<ve-histogram :data="chartData" :extend="chartExtend"></ve-histogram>
...

// mock 包含标注的数据结构
dataList: [
    {
        id: '1, 1, 3, 2',
        date: '2019-10-10',
        name: 'test-name1, test-name2, test-name3, test-name4'
    },
    ...
    {
        id: '1',
        date: '2019-10-17',
        name: 'test-name1'
    }
],
...

setChartExtend () {
    this.chartExtend = {
        series: (v) => {
            Array.from(v).forEach((e, idx) => {
                e.markPoint = {
                    data: getMarkPointData(this.chartData.rows, dataList)
                };
            });
        },
        ...
    };
},

getMarkPointData (rows, dataList) {
    const results = [];

    rows.forEach((row, index) => {
        // 通过日期匹配,找到对应的标注对象
        const dataItem = dataList.find(item => item.date === row.date);
        if (dataItem) {
            results.push({
                symbol: getSymbolUrl(dataItem.id),
                symbolSize: 15,
                coord: [index, 0],
                symbolOffset: [0, 0]
            });
        }
    });

    return results;
},

getSymbolUrl (id) {
    // 这里需要额外先做一层准备工作:将图标按 id 对应图标进行命名,然后传到自家的cdn上
    // 命名可以像这样:symbol-icon-1.jpg、symbol-icon-2.jpg 等等
    // 这里拿到标注的id,拼上链接返回即可
    // 形如:image://http://xxx.xxx.com/symbol-icon-1.jpg
    // 遇到多个 id 的情况,可以多加一个复合图标来处理,id 可以定为 0
}

因为 markPoint 在设置 data 时,取不到日期的数据,所以就需要用到 chartData 中的 rows 了。

在 rows 的循环中,如果匹配到当天需要打标记,则往结果数组中存入刚才预设的数据结构,最终返回给 markPoint 的 data,渲染展现。效果如下:

tooltip 的实现方法,不受图表的类型影响,是可以通用的,故此处不再赘述。

另外,有的时候,会遇到需要处理柱状图是否堆叠的效果。这会影响 symbolOffset 的定位,为了美观,可以这样处理:对于非堆叠的项,将之往右偏移 50%,将标记居中展示,即 symbolOffset : ['50%', 0]

折线图 + 柱状图

最后来个 组合拳,折线图与柱状图的复合型图表结构,像下面这样:

从代码实现上,我们当然可以给每一根符合条件的柱子,和折线的拐点,都打上标记。但在界面设计上,为了美观,我们选择只给折线的拐点打上标记,并且忽略了虚线的拐点。

这样的设计初衷是:标记,只是为了给人提个醒,是为了告诉查阅者,这一天因为发生了某些特殊事件,而导致数据发生了较为明显的变化。所以,由此得到的结论是:每天只要出现一个标记就够了。

具体的实现,其实很简单,只需要在渲染时判断 series 的 type 即可:

setChartExtend () {
    this.chartExtend = {
        series: (v) => {
            Array.from(v).forEach((e, idx) => {
                if (e.type === 'bar') {
                    // 设置柱状图 markPoint 的方法
                    ...
                }

                if (e.type === 'line') {
                    // 设置折线图 symbol、symbolSize 的方法
                    ...
                }
            });
        },
        ...
    };
}

总结

Echarts 可以实现的效果有很多,本篇涉及其中 “标记” 的渲染。在折线图的拐点处,用 symbol 做了匹配化的处理。在柱状图中,因为没有直接的 symbol,转而使用 markPoint 来实现,采用将标记定位在某个维度上的做法。效果都挺不错的。

不过,在后续的使用中,发现了另一个尴尬的情况:在折线图中,当点击图例中的某一项,使其数据隐藏,然后再次点击重新渲染后,发现 symbol 的自定义图标不显示了

我查了很久,还是没找到有用的信息。怀疑是个渲染的 bug,所以给 Echarts 提了 issue,希望能得到解决吧。也欢迎大家在留言区中,共同探讨相关的问题,感谢!

PS:欢迎关注我的公众号 “超哥前端小栈”,交流更多的想法与技术。

查看原文

赞 8 收藏 8 评论 1

micherwa 回答了问题 · 2019-10-28

webuploader传递图片或文件时,传递数组参数可以实现吗

你的意思是 uid 只能接收字符串?

将你的对象 JSON.stringify 一下,传给后端就好了,后端可以再转成对象处理的

关注 2 回答 2

认证与成就

  • 获得 980 次点赞
  • 获得 20 枚徽章 获得 1 枚金徽章, 获得 6 枚银徽章, 获得 13 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

  • Micherwa Blog

    个人博客,偏前端领域,致力于用通俗易懂的话术积累知识点。

  • vue-vuex-seed

    基于vue2全家桶的mobile种子工程,自定义了webpack4,并加入eslint,对代码规范进行实时监测。

  • react-redux-admin-seed

    基于react16 + router4 + react-redux5 + antd3.10 的后台管理种子工程,webpack从零开始,自建了v4版本的webpack.config.js。

  • vue-typescript-seed

    基于vue2.5+typescript2.6+vuex3的种子工程,将会继续完善基础组件及功能。

注册于 2017-07-27
个人主页被 3.6k 人浏览