常规音频产品会员,要如何进行转化漏斗设计?
会员转化本质上和其他转化没有太大区别,都是希望通过合理的转化路径和漏斗,促使用户产生购买行为。所以会员转化同样也和其他转化一样,需要设计一个合理完善的流量转化漏斗。那么,常规音频产品会员,要如何进行转化漏斗设计?
如今很多行业都开始注重会员的开拓,音视频行业也不例外,纷纷在原本的付费节目和广告的营收外,开拓会员的收入,为原有的免费节目加上了会员抢先听、会员免广告,付费节目加上会员打折,开拓会员免费听等会员附加权益,以促使用户购买会员。
会员转化本质上和其他转化没有太大区别,都是希望通过合理的转化路径和漏斗,促使用户产生购买行为。所以会员转化同样也和其他转化一样,需要设计一个合理完善的流量转化漏斗,而这个漏斗的目标是第一引导用户转化,提升产品整体的转化效率,第二减少流量流失率。
在我的实际操作中,我把它分为三步走:
在考虑路径之前,我们首先要明确我们的目标,也就是漏斗中的流量最大限度地转化,最小限度地流失,需要考虑三点:
基于以上三点,我需要寻找合理的路径,所谓合理的路径就是在不违反用户习惯的情况下,水到渠成的路径,那么也就要求我再流量自然流转的路径上升进行转化路径的延伸。
一般来说,音频产品的用户行为和路径如下:
(图1)
从上图来看,音频产品的核心是内容,流量是跟随内容流转的,那么我们就要再根据内容的自然流转的基础上,加一层转化路径,引导用户自然地进入这个转化漏斗。这个转化路径是必须基于自然路径的,如果违反自然转化路径,反而会导致用户混乱和永久流失。
根据以上分析,合理转化路径需要在自然流量路径上进行延伸,那么流量转化的基本模型应该这样:
(图2)
在这个模型的基础上,再根据实际转化路径考虑哪些,再次仔细观察音频产品的流量流转路径,不放过任何一个可能发生转化的路径。于是,我们所有这些承接内容和流量流转的关键位置:首页、频道、专题、节目、播放页。我
们可以看到,流量从首页进来,根据各个推荐位,固定入口或弹窗,分发到大致这样几个地方:分类频道、推荐专题、免费节目、付费节目、首页播放器、个人收藏、登录页,当然从频道、专题、收藏继续向下分发到免费付费的节目,再到播放页,个人收藏可能还会分发到收藏主播,再到节目,最终流向播放页。
既然要做会员转化,那么我们所期待的最终落地页应当是会员开通页,我做了两件事,第一将这些路径向下延伸打通到会员开通页,第二是在这些路径中加上用户跳转到会员开通页的HOOK。
这一部分先说如何延伸这些路径打通到会员开通页,我先根据(图1)路径,叠加会员转化路径后,一条一条梳理合理性(备注:括号中是非必要经过的路径):
(1)首页→(个人中心)→会员开通页
这条路径最短,但也最生硬,尤其是在用户对该产品会员权益感知度不深的时候风险最大。当然产品已经有了相当的产品接受度,可以考虑,比如说:饿了么,可以在首页引导开通会员免配送费等,就显得不是那么突兀。
按照这个逻辑,音频产品在这个环节引导购买会员在理论上也能成立。但实际情况,到目前为止,各音频产品的首页一般承担了推荐重要内容的目标,而且用户对产品的认知度未必达到饿了么的水准。
所以目前首页到会员开通这条路径在音频产品中很少有固定入口,但是在品牌向的,比如和腾讯产品的联合会员,会临时性地在首页进行露出曝光,这么做更大地是建立在用户对腾讯会员的认知度上。个人中心→会员开通页的路径还是比较常见的,个人中心本身也比较适合展示更多会员权益。
(2)首页→登录页→会员开通页
如果要享受会员权益,是必须要登录的。未登录状态一般是新用户,或已经长时间不活跃的用户了,如果在未登录的页面引导购买会员,在产品逻辑上不能说不通顺,但我认为不如在用户登录成功后,更加用户属性作差别化引导更加顺畅,可能转化效果也会更好,但是暂时还没有数据支持,这是我的一个尝试。
(3)首页→频道→会员开通页
这条路径也非常短,一般情况下风险和收益和首页→会员开通页是一样的。有一个不同的地方在于,如果这个频道主题和转化相关度较高,也同样合理。比如说:会员转化中的会员专区,能够详细说明会员权益,罗列会员商品,那么这条路径虽然生硬,但是合理。
(4)首页→(频道)→专题→会员开通页。
这条路径(首页可能直接推荐专题,未必要经过频道),只要专题设计合理,呈现具有吸引力的会员权益,利益点吸引力高,转化合理而自然。
(5)首页→(频道→专题)→免费/付费节目(具备会员权益)→会员开通页
用户到的达节目,应当是已经经过之前环节的有意识的引导,到达具备会员权益的节目,如果节目能吸引用户,节目本身附带会员权益,那么引导用户在这条路径上转化是合理可行的。
(6)首页→(频道→专题→具备会员权益的节目)→播放页→会员开通页
这里的播放页应该是经过有意识引导到达的具备会员权益的节目。目标用户应当是收听免费节目的用户,收听付费/会员节目的试听的用户,以及应购买该节目却并非会员的用户,此条路径和上条相似,只是到达这个位置的用户可能更加理性,对内容质量要求更高,那么如果内容足够好,同样是一条合理的路径。
(7)首页→播放器→播放页→会员开通页
此条路径的逻辑和上条相同,但是具体设置HOOK需要考虑用户其实有巨大差别,后文会具体分析。
(8)首页→收藏→主播主页(→节目→播放页)→会员开通页
既然用户收藏了该主播,说明该用户对该主播有一定忠诚度,那么如果能提供收看该主播的节目的权益,用户有购买会员可能,该路径可行。
那么可行的转化路径如下图(图3):
橙色的线条是从内容流转之后,延伸到会员转化的路径,上面还有部分在这张图里我改成红色的路径,它们原本是自然流转的路径,但是为了流畅地引导用户自然进入转化路径,它们也成为了转化路径的一部分,必须考虑进我们的转化策略。
也就是说,我在这些自然流转路径上进行有意识的引导,引导用户进入和会员权益有关联的产品中,接下来才能顺利进行会员引导。
(图3)
大致的流量漏斗完成之后,我们开始查找,还有什么地方,用户可能会跳出,流量会流失,我们还需要查漏补缺,让可能流失的流量继续回流,也就是说把用户引导到跟会员相关的内容专题或节目上,让用户再次进入上述的基本转化漏斗模型。
我发现我有两处漏洞:
对于这两处,没有引导到会员开通的理由,生硬地向会员开通页引导是非常奇怪的,跟用户当前需求有较大差距,无法激发用户点击兴趣,强行引导开通会员,流量流失非常大,不如向具有会员属性的付费节目或会员节目引导,引导用户进入转化漏斗。
最后,补充完整的转化路径如(图4):
(图4)
两个绿色的箭头便是以上两个漏斗的回流路径。
为了打通以上各路径,我计划设置合理且能打动用户的HOOK策略,也就是说在合理的位置上设置合理自然的HOOK,让用户沿着我们设计的路径完成转化。HOOK的目的在于两个:第一促进用户尽量以最短的路径转化,第二促进尽可能多的用户转化。
基于以上路径的模型,我把HOOK分为两大类,内容类HOOK和权益HOOK,暂且把它们叫做HOOK1和HOOK2,HOOK1的目标是促使用户对内容产生兴趣,进入跟会员相关的内容,HOOK2的目标则是在此基础上,叠加会员权益,引导用户开通会员。
按照以上分析,基本的HOOK策略如下:
(图5)
但是,因为实际的转化路径要比基本模型复杂很多,所以我们要分清楚那些从那么哪些的位置应当放什么HOOK?
在确定这个问题之前,我们先考虑用户分层和用户习惯。转化引导的HOOK不能太过于生硬或不合理,太过于急功近利可能反而会干扰用户,造成用户反感或迷茫,导致流量无可挽回的流失。所以首先,我们要在用户的自然流转路径上加合理自然的HOOK:在用户刚刚进入的时候,用内容HOOK让用户对产品有认知,当用户对内容产生浓厚兴趣时,用权益HOOK让用户产生购买行为。
那么也就是说,我要考虑每个路径的每个环节放置什么的HOOK,这也分两步走,第一确定适合设置哪一类HOOK,然后根据具体场景确定具体的HOOK。
根据上述策略,非常明显可以看出,原流量自然流转的路径环节设置HOOK1,引导到跟会员相关的内容上,比如:加入会员免费听、会员抢先听,会员打折等会员权益的节目上,通往会员开通也的环节自然应当设置HOOK2(如图6所示)。
(图6)
不过,即便是同样的内容路径环节和会员权益,根据不同的场景和功能,具体的设置和文案,也有千差万别。
(1)首页→(个人中心)→会员开通页
因为只有一个(两个)环节,而且不跟具体的内容具有强关联,所以这里更加适合针对重度用户呈现尽可能多的会员权益。
在实际操作作中,一般在音频行业很少会在首页设置固定的会员HOOK,第一,首页重度用户无论是程度和数量未必能达到足够的水准;第二,受到版面内容逻辑的影响。
当然,临时性的品牌向活动,比如:腾讯联合会员推广,将大众认知度高的腾讯会员作为一个HOOK2,是常见的操作。个人中心设置HOOK2,大篇幅展示会员权益,是比较常规的操作。
(2)首页→登录页→会员开通页
根据前面说的,在登录后跳转的页面根据用户数据进行差别化引导。对于新用户可以推荐试用7天会员,对于老用户,可以呈现用户权益,最好是能实现自动推荐用户感兴趣的并享受一定会员权益的内容的同时,引导开通会员。不过我的这个设想,暂时还没有数据支持(此处备注,有数据后加上)。
(3)首页→频道→会员开通页
这里看起来有两个流量流转环节,但其实跟上第一条转化路径区别不大,一般是某频道的重度的用户,有固定访问的频道。那么如果这个频道跟会员相关度较高,比如:该频道为会员专享频道,或该频道有统一的会员权益(一般为全频道会员免费)等等情况下,类似本品的为会员免费听等权益是比较合理的HOOK。比如:刚才说的会员专享频道,加入会员全场免费听,本身就是一个对重度用户非常具备吸引力的权益HOOK。
(4)首页→(频道)→专题→会员开通页
这个转化路径设置HOOK的关键位置是专题,那么专题的设计则需要和转化目标一致,比如:例子中的音频产品的会员转化,那么我们在选品的时候则需要选择包含会员权益的节目,比如会员免费听、会员抢先看、会员折扣等节目,让用户在专题页形成购买意愿,最终在专题上加一个会员开通页的入口,完成整个转化路径。
需要注意的是,专题中是有节目或者单集节目组成的,部分用户不会在当前页转化,而流转到下层的节目中,所以不能忘记埋下引导到下层节目的内容HOOK,以防用户直接跳出。所以依然不可忽视激发用户对节目感兴趣,进入节目的欲望。这样,即便用户在专题页暂时没有购买会员的欲望,依然不至于关闭页面,还能进入下一个转化路径。
综上所述,专题上需要有两个HOOK,第一是会员权益和开通页入口,第二便是从专题进入节目的内容及其推荐语。专题往往还会承接很多临时性活动,可以在专题中设置限时限量优惠等活动性HOOK,增加活动性和紧迫感。
这条转化路径是上一条路径的延伸,在上一层中没有转化的用户,经过引导到达具备会员权益的节目,所以这一层的HOOK关键位置是节目,并且这几乎已经是流量自然流转的最后一个环节。如果用户在这里不能转化,极大的几率在本路径上就不会发生转化了,所以必须抓住最后的机会。
那么我们除了在节目包装上提升节目质量,加大节目吸引力外,还需要在节目中告知购买会员的好处,这里需要根据节目跟会员的关联功能设置会员免费看,会员折扣(价格锚点),会员抢先听,会员去广告等等不同功能。
免费、付费、会员节目的具体权益可能不同,比如免费节目的会员权益可能是会员抢先听,会员去广告等;付费节目可能是会员折扣,还有加入会员专区的节目可能是会员免费听。当单个节目对用户的刺激还不够的时候,也可以适当考虑叠加推荐更多相同功能的相关节目,增加内容数量的吸引力。同样的,对于临时性活动可以增加限时限量优惠等活动性HOOK。
这里的目标用户要分4个情况:
针对免费节目收听用户和试听付费节目的用户的HOOK基本上和上一条相似,付费节目略有不同,已经是会员的用户暂且不是我们的目标用户,但是针对购买该节目但尚不是会员的用户,当前节目的权益对用户吸引力已经不是很大,那么我们需要吸引他们关注更多没有购买的,拥有会员权益的节目。
那么,在这个地方,我们则需要加入吸引用户关注其他拥有会员权益的节目内容推荐。同样的,如果该节目有临时性活动,在播放页也可以增加限时限量优惠等活动性的HOOK。
(7)首页→播放器→播放页→会员开通页
这条路径在播放页转化HOOK设置同上。
(8)首页→收藏→主播主页(→节目→播放页)→会员开通页
如果主播有跟会员权益相关的节目,可以在主播主页突出显示,强调加入会员可免费/抢先/优惠看该主播节目。
(9)其他
关于之前梳理路径的时候,提到的一开始被遗漏的两个漏洞:没有会员权益的节目及其播放页和已购的付费节目的播放页。之前提到,将流量引导到附加了会员权益的内容,重新加入转化漏洞中。也就是说这里需要加入内容型的HOOK,比如:推荐跟该节目内容有相关度的,也就是猜测用户可能感兴趣的,并附加了会员权益的节目,引导用户进入转化漏洞。
至此,完成了全部会员转化漏斗模型的HOOK。
召回是为了挽回已经流失的流量,分为2个层次:
在很多公司,这类用户的召回并不是在转化部门来做的。这里简单提一下,毕竟也是转化的潜在用户。对于这类用户,召回的方式是内容,而不是会员权益本身,采用推送和短信的方式,发送用户感兴趣的内容召回用户再次使用产品,进入我们的转化漏斗。
会员是一种有期限的商品,为了持续产生购买,定期对到期用户进行续订召回,应该是一种日常工作。当然,大多数的音频产品都有自动续订的功能。但也有很多用户并不选择自动续订,那么对于这部分用户,我打算定期召回。
召回的方式同样有两种:
在实际操作中,需要根据用户的行为来决定召回的策略。如果能判断用户正在听某个具有会员权益的节目,可以设置提醒功能,在用户会员即将到期的时候,自动提醒续费继续享受权益;如果有的节目第二季上线,也可以定向推送第一季的有效收听用户购买会员。
同理,我们也可以根据用户过往收听的专辑,推荐相关的内容,激发兴趣,再次进入转化漏斗。
当然,会员转化的效果不仅仅取决于转化漏斗设置是否完善,同样也取决于每个HOOK的转化率如何。
通俗来说,就是各个HOOK是否具有吸引力,这包含两个方面:
如果漏斗完善,而这些则需要不断测试优化,不断完善,关于内容的设计,暂时不在本文详述,以后在详细说吧。
最后,其中的遗漏和错误,希望得到指教,也希望能和大家一起探讨更好的模式。我也会在之后的运营中不断发现和补充。
本文由 @喵喵洞 原创发布于人人都是产品经理。未经许可,禁止转载
题图来自Unsplash,基于CC0协议
Rapper必懂:HIPHOP音乐常用基础术语!
这些名词你可能经常在HIPHOP音乐里面听到,但你知道是什么意思吗?
1.Intro
专辑里的引子或序曲
2.Bar
Rap里的一行词。行与行之间有停顿。
3.Verse
主歌。Verse由Bar组成,一般来说,一段Verse有16Bars,一首Rap歌曲有2段或3段Verse组成。
4.Hook /Chorus
副歌。副歌可以是Rap,也可以是吟唱,但一般都比较简短,而且往往朗朗上口,意味深长,情感浓度高,并常点明和升华歌曲的主旨。一般用于歌曲的开头、收尾以及Verse之间的衔接。
5.Rhyme
押韵,韵脚。
6.Flow
指Rap时对停顿、重读、速度、呼吸、押韵等说唱要素的把握和驾驭。100个Rapper会有超过100种Flow,所以这就是为什么不同的Rapper就着同一个伴奏、同一段歌词却能玩出不同的感觉,当然,有些能掌握多种Flow的Rapper也能玩出就着同一个伴奏、同一段歌词多种感觉。
7.Freestyle
即兴发挥。你的歌词、唱法等都是临时准备或者即兴发挥的。
8.Punchline
点睛之笔。说唱里面就是指歌词的炸点,这个部分的韵律、节奏等,会使演唱者和听众都觉得十分完美。
9.Chorus
原意是指合唱,说唱里面指和声部分。
10.AKA
Also Known As的简写,直译就是“也可以被称作”、“也可被叫作”,就是“绰号”的意思。
11.You know/You know what i am saying/You getti:
你懂的!/你懂我意思吗?
12.Dope
牛逼。Dope原意是毒品的意思,到后来就是“爽”、“嗨”的意思,到现在就是感觉很牛逼的意思了。”
13.O.G:
有很多单词的缩写都是O.G.而在西海岸说唱文化中常常提到的O.G是“Original Gangster”的缩写,可以译做“真正的大佬”、“纯正的匪帮”。
14.check it out
马上开始,请认真听。
15.Demo
样本、演示、小样,说唱里面指未制作完成的半成品。
16.What's up
打招呼时指“最近怎么样?”“近来可好”等招呼的口语。特殊时候的凶狠语气的“What's up”有威胁、挑衅的意思:“你要撒子嘛!!!”
17.Swag
范儿、拽、酷炫、潮
18.Nigga
黑鬼。只有黑人对黑人说意思是“朋友、哥们儿",你皮肤不是黑的,就别对他们说这个单词,带有侮辱性。
19.Homie
哥们儿、兄弟伙、死血、叉叉裤兄弟
20.Gangster
匪帮、帮派分子
21.Keep Real
有字幕组翻译是“别”,教程君觉得是“做自己”更合适。保持真实,你是怎样一个人,说唱就该那样。
22.Mic drop
在表演结束故意扔掉麦克风,以此来引人瞩目
23.break
指在节奏中的停顿和休息
24.Lay back
比节奏稍慢,以一个比较舒服的跟拍进入主歌
25.单押/双押
尾字押韵1个字/2个字
26.分押
分词押韵,示例:我来自成都(u),也叫作天府(an u)之国,你还想先睹(an u)为快…
27.换字押韵
那些故事书的标签都是已读(i u)
翻烂的字典泛滥的词汇比如(i u)
snoopy(u i) 我记录又记录(i u)
28.夹韵押
那是一些老照片(ao an) 里面有着一堆故事(u i)
那个鸭舌帽的帽檐(ao an) 诉说我们从前的固执(u i)
29.连字押韵
六字以内连续押韵叫作连字押韵,示例:
那些故事(u i)被物质(u i)摧残得物是(u i)人非
30.回韵
一句到三句之内回韵脚叫作回韵,示例:
那些年少的情愫(u) 变成了密码
而那些从前的爱人 就被专辑收录(u)
31.换韵
从这里开始联想从前(ong an) 从火车站到湖边到某个公园(ong an)
那些香甜的记忆(i i) 都是虚无的秘密(i i)
32.完美换韵
通过连韵技巧换韵,示例:
请记住(i u) 那诺言没有人或选项将它删除(an u)
跟情话一起 甜蜜中却没有丝毫贪图(an u)
就像安徒(u)生的童话(a) 像冰糖般融化(a)在那梦里(i)
33.双声之禁
两个字声母相同的词,为双声词。双声词中有一个韵母中的字母相同,比如鱼(yu)月(yue),这种词很绕口,如果你并不是下定决心要唱,尽量避免,否则很容易连音绕过去。
34.Cypher/Mic pass
说唱接力。每人接麦克风来一段说唱,要是到你唱不出来就十分尴尬了。
35.Battle
对战,较量。两个选手之间互相带有攻击性说唱的比赛,在battle里基本都是用freestyle来互相反驳哦,不仅考验实力、智力、还得考验怼人功力,用对方的弱点、黑点来攻击,简直不要更刺激!
36.Diss
可以理解为Disparage(蔑视,贬低,批判)和Disrespect(不尊重)的简称。
这是区别于Rap Battle的。Rap Battle虽然双方会互相贬低和批判,但初衷一般是在说唱技巧上一较高下,分出高低胜负。而Diss Track则一般是有条有理的来贬低一个人或者说对手。如果Battle是一场拳击赛,那么Diss Song则是一场精心策划的。
37.Beef
矛盾,争端。HipHop史上最著名的Beef就是2pac挑起的“东西海岸战争”。
38.DJ
什么?Disk Jockey?唱片骑士?什么鬼?!谁告诉你的?他一定不懂Deejay这词吧!DJ=Deejay!意为播放音乐的人!这就是为什么电台音乐节目的主持人也叫DJ!况且,正常人都不会把放音乐的人称为唱片骑士好吧?!当然,在HipHop术语里,DJ的含义也绝非“播放音乐的人”的人那么简单。而第一个为HipHop里的“DJ”下定义的就是被人尊称为“HipHop之父”的Kool Herc。上世纪70年代,普通青年开Party都是播放可以活跃流行歌曲,而这些流行歌曲里有一些用于过渡的间奏,这些间奏没有歌词而且一般比较High,但这些间奏一般都很短,刚High起来就没了,难以令人尽兴。想象力丰富的Kool Herc为了使这些间奏延长甚至根本停不下来,他想了个好办法:(不是吃炫迈……)那就是架设两台唱盘机,播放两张同样的唱片,当一台唱盘机把令人兴奋的间奏放完的时候,就用手把唱片转回来,同时用另一台唱盘机播放那段间奏,如此反复运作,便可以令Party的气氛持续的High。后来,又经过许多DJ的丰富,形成了如今的DJ文化。
39.DJ drop the beat
顾名思义就是:老铁,放歌吧!
40.MC
什么?Micphone Controller?麦克风控制者?又是哪个人告诉你的?MC=Emcee!原意为主持人。话说Kool Herc觉得连续播放流行歌曲的间奏依旧不够High,于是请了他的朋友Coke La Rock和Clark Kent来做主持人,帮他活跃气氛。但是,他们说的话可不是Rap,而是来自牙买加的Toasting。所以严格来说,这两位前辈其实并不算当今HipHopper说的那种“MC”。但他们却开创了DJ+MC组合的先河。要说第一批给HipHop里“MC”下定义的,便是另一名元老级Grandmaster Flash 身边的MC团队the Furious Five。
41.Hype man
舞台助场伴唱。大家在看HipHop表演现场会的时候都会发现一个现象,那就是一首说唱歌曲由于歌词密集,语速很快,往往导致在现场演出的时候Rappers不能完美的唱出整首歌。而这时候就需要一个帮手来帮助Rapper唱出部分歌词(往往是韵脚),以此来更加完整的表现一首说唱歌曲,他们就是所谓的Hype man。大家千万不要简单的认为Hype man就只是负责给主唱打下手,相反,Hype man并不是一个固定的头衔,在Rap歌曲现场表演的时候,舞台上的歌手往往会互相做彼此的Hype man. 而且Hype man的职责不仅是跟着节奏来唱几句词而已,Hype man还需要灵活的调动音乐会现场的气氛,在舞台上带动观众的兴致等等。
42.Remix
混音。简单的说就是将多个音轨进行和谐的混合,对原曲进行再编辑,演绎出新的味道。
43.Mixtape
杂集合锦。Rapper们往往将已授权的音乐加以混音、衔接,唱入自己的歌词将原曲再版,它的重点在于其歌词内容和思想,这种随意又自由的方式是Rapper们证明实力与宣传的最佳途径。
44.Beat
节奏。只有节奏踩得准,你的说唱听起来才比较有律动。
最后要用一个词来完美总结
45.Peace
和平、安好。黑人喜欢用“Peace”表达再见,有点“走好、一路顺风”的意思。
陈伟霆野狼disco在哪里可以听 陈伟霆野狼disco完整版歌词
useState 可以说是我们日常最常用的 hook 之一了,在实际使用过程中,有一些简单的小技巧能帮助你提升性能 & 减少出 bug 的概率。
通常我们会使用以下的方式初始化 state。
对于简单的初始值,这样做完全没有任何性能问题,但如果初始值是根据复杂计算得出来的,我们这么写就会产生性能问题。
相信你已经发现这里的问题了,对于 useState 的初始值,我们只需要计算一次,但是根据 React Function Component 的渲染逻辑,在每一次 render 的时候,都会重新调用该函数,因此 initalState 在每次 render 时都会被重新计算,哪怕它只在第一次渲染的时候被用到,这无疑会造成严重过的性能问题,我们可以通过 useState 的惰性初始值来解决这个问题。
不要把只需要计算一次的的东西直接放在函数组件内部顶层 block 中。
当我们想更新 state 的时候,我们通常会这样调用 setState。
看上去没有任何问题,我们来看看另外一个 case。
点击 div,我们可以看到计数器增加,那么 3 秒过后,计数器的值会是几呢?
答案是 1
这是一个非常反直觉的结果,原因在于第一次运行函数时,state 的值为 0,而 setTimeout 中的回调函数捕获了第一次运行 Demo 函数时 state 的值,也就是 0,所以 setState(state + 1)执行后 state 的值变成了 1,哪怕当前 state 值已经不是 0 了。
让我们通过函数式更新修复这个问题。
让我们再运行一次程序试试,这次 3 秒后,state 并没有变成 1,而是增加了 1。
直接在 setState 中依赖 state 计算新的 state 在异步执行的函数中会由于 js 闭包捕获得到预期外的结果,此时可以使用 setState(prev => getNewState(prev)) 函数式更新来解决。
相信很多同学听过 immer.js 这个库,简单来说就是基于 proxy 拦截 getter 和 setter 的能力,让我们可以很方便的通过修改对象本身,创建新的对象,那么这有什么用呢?我们知道,React 通过 Object.is 函数比较 props,也就是说对于引用一致的对象,react是不会刷新视图的,这也是为什么我们不能直接修改调用 useState 得到的 state 来更新视图,而是要通过 setState 刷新视图,通常,为了方便,我们会使用 es6 的 spread 运算符构造新的对象(浅拷贝)。
我相信你已经发现问题了,对于嵌套层级多的对象,使用 spread 构造新的对象写起来心智负担很大,也不易于维护,这时候聪明的你肯定想到了,我直接 deepClone,修改后再 setState 不就完事了。
这样就完全没有心智负担的问题了,程序也运作良好,然而,这不是没有代价的,且不说 deepClone 本身对于嵌套层级复杂的对象就非常耗时,同时因为整个对象都是 deepClone 过来的,而不是浅拷贝,react 认为整个大对象都变了,这时候使用到对象里的引用值的组件也都会刷新,哪怕这两个引用前后值根本没有变化。
有没有两全其美的方法呢?
当然是用的,这里就要用到我们提到的 immer.js 了。
这里我们可以看到,即使用了 deepClone 没有心智负担的写法,同时 immer 只会改变写部分的引用 (也就是所谓的“Copy On Write”),其余没用变动的部分引用保持不变,react 会跳过这部分的更新,这样我们就同时获得了简易的写法和良好的性能。
事实上,我们还可以使用 useImmer 这个语法糖来进一步简化调用方式。
可以看到,使用 useImmer 之后,setState 几乎跟原生的 useState提供的函数式更新 api 一模一样,只不过,你可以在 setState 内直接修改对象生成新的 state ,同时 useImmer 还对普通的 setState 用法做了兼容,你也可以直接在 setState 内返回新的 state,完全没有心智负担。
前面讲了useState,那么还有一个开发过程中最常用的就是 useEffect 了,接下来来聊聊我的日常使用过程中 useEffect 的坑吧。
在很多情况下,我们可能会写出这样的代码
咋一眼看上去没有任何问题,dep1 这个 state 变动的时候我更新一下 dep2 的值,然而这其实是一种反模式,我们可能会习惯性的把 useEffect 当成一个 watch 来用,但每次我们 setState 过后,函数组件又会重新执行一遍,useEffect 也会重新跑一遍,这里你肯定会想,那不是成死循环了,但其实不然,useEffect 提供的第二个参数允许我们传递依赖项,在依赖项不变的情况下会跳过 effect 执行,这才让我们的代码可以正常运行。
所以到这里,聪明的你肯定已经发现问题了么?
要是我 dep 数组写的不对,那不是有可能出现无限循环?
在实际开发过程中,如此高的心智负担必然不利于代码的维护,因此我们来聊一聊什么是 effect,setState 又该在哪里调用,我们来看一个图:
这里的 input / output 部分即 IO,也就是副作用,Input 产生一些值,而中间的纯函数对 Input 做一些转换,最终生成一堆数据,通过 output driver 执行副作用,也就是渲染,修改标题等操作,对应到 React 中,我们可以这样理解。
所有使用 hook 得到的状态即为 input 副作用产生的值。
function 组件函数本身是中间转换的纯函数。
React.render 函数作为 driver 负责读取转换好之后的值,并且执行渲染这个副作用 (其它的副作用在 useEffect 和 useLayoutEffect中执行 )。
基于以上的心智模型,我们可以得出这么几个结论:
(提醒一下,直接在函数顶层 block 中调用 setState,if 条件一下没写好,组件就挂了)
我们可以使用这种方式计算新的 state。
(注意这里并没有使用 useMemo )
在 React 中,每次渲染都会重新调用函数,因此直接写在函数体内的自然就是 compute state ,在没有严重性能问题的情况下不推荐使用 useMemo, 依赖项写错了容易出 bug。
如果你写过以下的代码:
这样的代码非常容易造成循环依赖的问题,而且一旦出了问题,非常难排查很解决,整个 state 的更新很难预测,相关的 state 更新如果建议一次更新 (可以考虑使用 useReducer 并且在可能的情况下,尽量将状态更新放到事件而不是 useEffect 里)。
在多个组件共享状态以及要向深层组件传递状态时,我们通常会使用 useContext 这个 hook 和 createContext 搭配,也就是下面这样:
这也是 React 官方推荐的共享状态的方式,然而在需要共享状态的组件非常多的情况下,这有着严重的性能问题,在上述例子里,哪怕 A 组件只更新 state.a,并没有用到 state.b,B 组件更新 state.b 的时候 A 组件也会刷新,在组件非常多的情况下,就卡死了,用户体验非常不好。好在这个地方有很多种方法可以解决这个问题,这里我要推荐最简单的一种,也就是 react-tracked(react-tracked.js.org/) 这个库,它拥有和 useContext 差不多的 api,但基于 proxy 和组件内部的 useForceUpdate 做到了自动化的追踪,可以精准更新每个组件,不会出现修改大的 state,所有组件都刷新的情况。
一个很常见的误区是为了心理上的性能提升把函数通通使用 useCallback 包裹,在大多数情况下,javascript 创建一个函数的开销是很小的,哪怕每次渲染都重新创建,也不会有太大的性能损耗,真正的性能损耗在于,很多时候 callback 函数是组件 props 的一部分,因为每次渲染的时候都会重新创建 callback 导致函数引用不同,所以触发了组件的重渲染。然而一旦函数使用 useCallback 包裹,则要面对声明依赖项的问题,对于一个内部捕获了很多 state 的函数,写依赖项非常容易写错,因此引发 bug。所以,在大多数场景下,我们应该只在需要维持函数引用的情况下使用 useCallback,例如下面这个例子:
这里我们需要在组件卸载的时候移除 event listener callback,因此需要保持 event handler 的引用,所以这里需要使用 useCallback 来保持引用不变。
然而一旦我们使用 useCallback,我们又会面临声明依赖项的问题,这里我们可以使用 ahook 中的 useMemoizedFn(ahooks.js.org/zh-CN/hooks…) 的方式,既能保持引用,又不用声明依赖项。
是不是觉得很神奇,为什么不用声明依赖项也能保持函数引用不变,而内部的变量又可以捕获最新的 state,实际上,这个 hook 的实现异常的简单,我们只需要用到 useRef 和 useMemo。
所有需要用到 useCallback 的地方都可以用 useMemoizedFn 代替。
对于需要优化渲染性能的场景,我们可以使用 memo 和 useMemo,通常用法如下:
考虑到 useMemo 需要声明依赖项,而 memo 不需要,会自动对所有 props 进行浅比较 (Object.is),因此大多数场景下,我们可以结合上面提到的 useImmer 以及 useMemoizedFn 保持对象和函数的引用不变,以此减少不必要的渲染,对于 Context 共享的数据,我们可以使用 react-tracked 进行精准渲染,这些库的好处是不需要声明依赖项,能减小维护成本和心智负担,对于剩下的没法 cover 的场景,我们再使用 useMemo 进行更细粒度的渲染控制。
相对于上文中提到的这些 hook,useReducer 是我们日常开发过程中很少会用到的一个 hook (因为大部分需要 flux 这样架构的软件一般都直接上状态管理库了)。
但是,我们可以思考一下,在很多场景下,我们真的需要额外的状态管理库么?
我们来看一下下面的这个例子:
这是一个非常简单的计数器例子,虽说运作良好,但是却反映了一个问题,当我们需要同时操作一系列相关的 state 时,在不借助外部状态管理库的情况下,随着程序的规模变大,函数组件内部可能会充斥着非常多的 setState 一系列 state 的操作,这样视图就和实际逻辑耦合起来了,代码变得难以维护,但其实我们不一定需要使用外部的状态管理库解决这个问题,很多时候 useReducer 就能帮我们搞定这个问题,我们尝试用 useReducer 重写一下这个逻辑。
我们先写一个 reducer 的纯函数:
如果看到这里,你已经忘记了reducer之类的概念,我们来复习一下吧。 reducer 通常是一个纯函数,它接受一个action和一个payload,当然还有上一次的state,基于这三者,reducer计算出next state,就是这么简单。
我们再来定义一下初始状态以及 action 类型:
接下来只要用 useReducer 把他们组合起来就行了:
这样我们就把 reducer 这个状态的变更逻辑从组件中抽离出去了,代码看起来清晰易懂,维护起来也方便多了。
Q: reducer 是个纯函数,如果我需要获取异步数据呢?
A: 可以使用 use-reducer-async(github.com/dai-shi/use…) 这个库,只要引入一个极小的包,就能拥有 effect 的能力。
React Hook 心智负担真的很重,希望 react-forget (zhuanlan.zhihu.com/p/443807113… production ready。
盘点说唱中的专业术语,你是否真的懂?
当陈伟霆遇上《野狼disco》是什么感觉,现在陈伟霆亲自告诉我们了,还为大家带来了这一首歌曲,那么陈伟霆野狼disco在哪里可以听?一起来看看陈伟霆野狼disco完整版歌词吧!
陈伟霆野狼disco在哪里可以听
说起今年最火爆的神曲《野狼disco》相信大家一定都不陌生,作为一首在极短时间内火速蹿红的神作,《野狼disco》可谓席卷了大江南北,不论走到哪里都能听到这首经典歌曲,而其演唱者董宝石也因此一举成名,从地下说唱圈走上主流舞台。
不过关于这首歌其实一直以来评论都比较两极化,喜欢的朋友特别喜欢,认为《野狼disco》唱出了一代人的回忆,是早期东北人民对香港纸醉金迷生活的向往,尤其是歌中董宝石的散装粤语,更生动形象地展现出了那一辈人的情怀。
不过就在今天一首不再是散装粤语的《野狼disco》版本正式上线,其中rap部分依然是由董宝石演唱,但在hook部分的“心里的花,我想要带你回家,在那深夜酒吧,哪管他是真是假”则交给了一位非常著名的歌手(兼演员)陈伟霆来完成。
不知道大家听了没有,没想到这种土嗨歌都可以唱的那么苏,跟着陈伟霆的野狼disco画了一天的龙了,真的要给我笑死了,现在在各大音乐平台都是可以听的哦,大家赶紧去看看吧,看有没有给你带来不一样的惊喜!
陈伟霆野狼disco完整版歌词
宝石Gem、陈伟霆 - 野狼Disco
作词:宝石Gem
作曲:宝石Gem
制作人:廖志华
编曲:IHAKASI
录音工程师:宋舒蕾@Tweak Tone Labs
录音棚:Tweak Tone Labs
混音:Double 魏玮 @NERDYBOY Production
后期母带处理:Double 魏玮 @NERDYBOY Production
OP、SP:飒娱
哎陈伟霆 干啥呢 能听着不
喂喂喂 走啊蹦迪去啊
唉 听到吗 你没动静啊
你怎么 某信号 没信号啊 挂了啊
陈伟霆:
心里的花
我想要带你回家
在那深夜酒吧
哪管它是真是假
请你尽情摇摆
忘记钟意叻Ta
你系最迷人噶
你知道吗
宝石Gem:
这是最好的时代
这是最爱的时代
前面儿哪里来的大井盖
我拿脚往里迈
如此动感的节拍
非得搁门口耍帅
我蹦迪的动线上面儿
怎么能有障碍
大背头
BB机
舞池里的007
东北初代霹雳弟
DJ瞅我也着急
不管多热都不能
脱下我的皮大衣
全场动作必须跟我整齐划一
来 左边 跟我一起画个龙
在你右边 画一道彩虹 走起
来 左边 跟我一起画彩虹
在你右边 再画个龙 别停
在你胸口上比划一个郭富城
左边儿右边儿摇摇头
两个食指就像两个窜天猴
指向闪耀的灯球
哪管它是真是假 是真是假
请你尽情摇摆
忘记钟意叻ta 钟意叻ta
你是最迷人噶
你知道吗
我好钟意你
宝石Gem:
玩儿归玩 闹归闹
别拿蹦迪开玩笑
左手一瓶大绿棒儿
右手霹雳手套
金曲野人的士高
都给我往后稍一稍
没事儿不要联系我
大哥大这没信号
小皮裙儿 大波浪
一扭一晃真像样
她的身上太香
忍不住想往上靠
感觉自己好像梁朝伟
在演无间道
万万没想到
她让我找个镜子照一照
歌照放嗷 舞照跳嗷
假装啥也不知道嗷
没有事 没有事
我对着天空笑一笑
使劲儿扒拉扒拉
前面儿社会儿摇的小黄毛儿
气质再次完全被我卡死 哎呀我去
来 全场 一起跟我 低下头儿
左手右手往前游
捂住脑门儿晃动你的胯胯肘
好像有事儿在发愁
忘记钟意叻他
你系最迷人噶
你知道吗 你知道吗
宝石Gem:
Ladies Gentleman
All the party people
给你最劲爆的舞曲
给你最摇摆的节奏
Let's happy tonight
今夜让我们一起放松
全场的帅哥美女
让我看见你们的双手
这是DJ Candy
MC小龙
欢迎莅临野狼Disco
来 左边 跟我一起画个龙 Hey
在你右边 画一道彩虹 哎哎
来 左边 跟我一起画彩虹 哎呀
在你右边 画个龙 哎呀哎呀哎呀
在你胸口上比划一个郭富城
左边儿右边儿摇摇头 哎整得好
两个食指就像两个窜天猴
指向闪耀的灯球 没毛病
来 全场 一起跟我 低下头儿
左手右手往前游 往前游啊
时时刻刻
必须要提醒你自己
不能搭讪
搭讪你就破功了 老弟
喂 伟霆啊
哎呀妈你这信号也忒差了
忙啥呢 又开演唱会呢
对啊老铁
我一个人撑不住啊
过来帮帮忙呗
能 能给 能给 能给多少钱啊你啊
真的太魔性了,你还在等什么呢?赶紧跟着大家的节奏吧!