用户行为分析模型实践(四)—— 留存分析模型

news/2024/5/19 10:04:15

作者:vivo 互联网大数据团队- Wu Yonggang、Li Xiong

本文是vivo互联网大数据团队《用户行为分析模型实践》系列文章第4篇 -留存分析模型。

本文详细介绍了留存分析模型的概念及基本原理,并阐述了其在产品中具体实现。针对在实际使用过程问题,探索了基于ClickHouse留存分析模型实践方案。

一、背景需求

根据CNNIC的统计数据显示,中国互联网用户已达10.79亿人,互联网普及率达到79.4%。互联网虽然仍然在快速增长,但是用户规模逐渐饱和,互联网事实上已经进入了存量用户时代,整体的流量竞争也越来越激烈,用户的留存的重要性也越来越高于拉新。因此,如何识别忠实用户,了解目标用户群的留存表现?如何分析用户流失情况,优化产品?如何分析目标用户是否完成了期望的行为等等就是我们数据分析的重要课题,而留存分析模型就是我们解决这些问题的重要工具。

二、概述

2.1 概念介绍

留存分析模型主要用于分析触发了起始事件的用户在后续时间周期内触发了后续事件(即回访事件)的比率,该模型可以较好的反映出用户的忠实度或者说是用户的粘性。对于留存分析模型有几个重要的概念要了解:

图片

留存分析一般需要指定起始事件和回访事件,但起始事件和回访事件可以相同,也可以不同:

1、起始事件、回访事件可以选择相同事件,这种可以很直观地看出触发事件的忠实用户量。

例如:在签到过程中,起始事件为签到成功,回访事件也是签到成功,在一段时间内,连续触发该事件的用户数量即可为忠实用户量。

2、起始事件、回访事件可以选不同事件,这种就是比较正常流程下的用户留存数据。

例如:在某个活动中,从下单到成功支付的场景内,起始事件为下单,回访事件为支付成功,这种在一段时间内,触发这两个事件的同一用户为指定流程下的用户留存数据。

2.2 分析思路

留存率作为一个产品的核心指标之一,我们提升产品力,改善使用体验,分析目标用户很大程度上也是为了提升这个指标。比如,我们可以通过计算N日的留存率,来评估某个迭代是否是正向的。如图1所示,某应用优化了首页布局,推出了新版本A,就可以联同旧版本B,分别计算每日的用户留存率,它一般会组成一个衰减的留存曲线。曲线衰减的越慢,说明我们的留存率越高,也就能体现我们首页的修改是有正向的效果的。当然有时留存的提升可能只有百分之零点几,但是在一个很大的用户基数的前提下,也可能产生一些质变的效果。我们也可以将特定的人群圈定为用户组,针对不同的用户组进行留存分析,挖掘更加忠实的用户群体。

图片

图1  新版本A与旧版本B的留存对比

三、用留存进行的数据分析

了解了上面的关于留存模型的基本概念,我们看一下如何创建一个留存。

3.1 选一个起始事件、一个回访事件

起始事件:打开浏览器。

回访事件:退出浏览器。

3.2 设置留存天数

设置一个留存天数为3天。

3.3 确定留存的时间区间

这里的时间区间概念是指,你需要查看的日期区间,例如选择时间区间为2023-01-06~2023-01-08,则是只计算2023-01-06到2023-01-08这3天,每天的当日留存,第1日留存,第2日留存,第3日留存。

3.4 留存数据的展示及计算逻辑

起始用户数 = 计算日期触发起始事件用户数。

  • 当日留存用户数 = 当日触发回访事件的用户与当日触发起始事件用户交集。

  • 第1日留存用户数 = 次日触发回访事件的用户与计算日期触发起始事件用户交集。

  • 第2日留存用户数 = 2日后触发回访事件的用户与计算日期触发起始事件用户交集。

  • 第3日留存用户数 = 3日后触发回访事件的用户与计算日期触发起始事件用户交集。

  • 当日留存率 = 当日留存用户数/起始用户数*100%。

  • 第1日留存率 = 第1日留存用户数/起始用户数*100%。

  • 第2日留存率  = 第2日留存用户数/起始用户数*100%。

  • 第3日留存率  = 第3日留存用户数/起始用户数*100%。

用户留存数表(即表1)表示起始事件为“打开浏览器”、回访事件为“退出浏览器”时,对应2023-01-06~2023-01-09每天的近3天的留存用户数据。

图片

表1 用户留存数表

用户留存率表(即表2)表示 起始事件为“打开浏览器”、回访事件为“退出浏览器”时,对应2023-01-06~2023-01-08每天的近3天的留存用户占比数据。

图片

表2 用户留存率表

以表1中2023-01-06日的数据为例,1月6日起始用户数1000:是指触发起始事件“打开浏览器”的用户数;当日留存用户数900:是指在触发起始事件用户中当日又触发回访事件为“退出浏览器“的用户人数;

第1日留存用户数500:是指1月7日触发回访事件且与1月6日中触发起始事件的交集用户数;第2日留存用户数300:是指1月8日触发回访事件且与1月6日中触发起始事件的交集用户数300,以此类推到第3日,此时计算出来的2023-01-06这一天的3天的留存数据!

图片

图2:触发起始事件、回访事件对应3日内的留存用户趋势图

四、整体功能设计及留存分析模型的实现

4.1(离线)功能整体架构设计

图片

图3 留存分析模型hive架构图

整体架构主要分为配置、计算、存储、展示四阶段。

1. 配置

此阶段主要是工程端的后台服务实现。用户在平台按照自身需求设置起始事件及回访事件、过滤条件、用户群筛选、维度筛选等配置。后台服务收到配置请求后,依据留存分析类型选择不同任务组装器进行sql任务的组装。

2. 计算

平台根据接收到的查询方式,选择离线查询Spark引擎进行分析计算。离线计算结果同步到MySQL。

3. 存储

离线结果集持久化到MySQL数据库中,可通过后台服务展示给用户。

4. 展示

离线结果根据图表配置ID查询MySQL结果表数据进行展示,即时查询通过配置后直接查询展示结果。

4.2(离线)留存不同条件下实现SQL

离线通用执行hive任务SQL

离线留存hive执行SQL

select'起始留存计算日期' as origin_day,a.day as day,datediff('起始留存计算日期', a.day) as diff,count(distinct (a.uid)) as user,count(distinct (case when b.uid is not null then b.uid end)) as retention
FROM(SELECTday,uidFROMabcd.testWHEREday >= if('起始时间' >= date_sub('起始留存计算日期', '留存天数'),'起始时间',date_sub('起始留存计算日期', '留存天数'))AND day <= if('结束时间' <= '起始留存计算日期','结束时间','起始留存计算日期')AND event_id = '起始事件')) a
LEFT JOIN (SELECTs.uid     FROMabcd.test s         WHEREs.day = '起始留存计算日期'AND s.event_id = '回访事件'                    GROUP BYs.uid
) b ONa.uid = b.uid
WHEREday >= if('起始时间' >= date_sub('起始留存计算日期', '留存天数'),'起始时间',date_sub('起始留存计算日期', '留存天数'))AND day <= if('结束时间' <= '起始留存计算日期','结束时间','起始留存计算日期')
GROUP BY a.day

SQL 当中字段含义分别为:

【origin_day】:起始留存计算日期

【day】:最终留存计算日期

【diff】:第几日留存

【user】:起始用户数

【retention】:留存数

以上SQL含义:查询起始留存计算日期分别到起始时间、结束时间这个区间段中的每天的详细留存数据,不可一次性计算出时间区间内完整的留存数据,需经过多天累计查询,且此SQL执行的结果在留存结果表中展示样例为倒三角填充。

例如:我们定了起始事件和回访事件后,去计算2022-05-01~2022-05-05的每一天的3日留存,此时,起始时间是2022-05-01,结束2022-05-05,留存天数3天。

针对此案例,起始留存计算日期开始日期应该为2022-05-01~2022-05-08,才能计算出2022-05-01~2022-05-05的每一天的3日留存。

第一步:计算起始留存日期 = 2022-05-01时,最终留存计算日期区间2022-05-01~2022-05-05日每天的留存数据,从时间上看,该起始留存计算日期只能计算出2022-05-01日当日留存,执行后结果如下(表3):

图片

表3  起始留存计算日期2022-05-01在2022-05-01~2022-05-05区间内留存详情数据

此时转换后留存数据表格为(表4):

图片

表4 起始留存计算日期2022-05-01在2022-05-01~2022-05-05区间内转换后留存数据表

第二步:计算起始留存日期 = 2022-05-02时,最终留存计算日期区间2022-05-01~2022-05-05日每天的留存数据,该起始留存计算日期可计算2022-05-01日的第1日留存用户数及2022-05-02日当日留存用户数据,执行后结果如下(表5):

图片

表5  起始留存计算日期2022-05-02在2022-05-01~2022-05-05区间内留存详情数据

此时转换后留存数据表格为(表6):

图片

表6 起始留存计算日期2022-05-02在2022-05-01~2022-05-05区间内转换后留存数据表

第三步:计算起始留存日期 = 2022-05-03时,最终留存计算日期区间2022-05-01~2022-05-05日每天的留存数据,该起始留存计算日期可计算2022-05-01日的第2日留存用户数、2022-05-02日第1日留存用户数据、2022-05-03日当日留存用户数据,执行后结果如下(表7):

图片

表7 起始留存计算日期2022-05-03在2022-05-01~2022-05-05区间内留存详情数据

此时转换后留存数据表格为(表8):

图片

表8 起始留存计算日期2022-05-03在2022-05-01~2022-05-05区间内转换后留存数据表

第四步:以此类推,计算起始留存日期 = 2022-05-08时,最终留存计算日期区间2022-05-01~2022-05-05日每天的留存数据,该起始留存计算日期可计算2022-05-05日的第3日留存用户数,执行后结果如下(表9):

图片

表9 起始留存计算日期2022-05-08在2022-05-01~2022-05-05区间内留存详情数据

最终数据展示完全后会是一个完整的表格(可得如下结果表10):

图片

表10 2022-05-01~2022-05-05的每一天的3日留存数据表

4.3 存在的问题与下一步优化的方向

存在的问题:

用户在平台上进行报表创建后,在产出报表结果上耗时较长;当配置报表查询周期长,数据量大的情况下,存在计算资源消耗过大的情况。

优化方向:

为了优化报表生成过程,可以考虑使用ClickHouse来处理数据。ClickHouse是一个高性能、分布式、列式存储的数据库系统,特别适合处理大规模数据和复杂查询。

具体而言,可以采用以下ClickHouse特性

  • 将数据导入ClickHouse中,以便更快地查询和计算。ClickHouse支持高效的数据导入和压缩方式,可以大大减少数据的存储空间和查询时间。

  • 利用ClickHouse的列式存储和分布式计算能力,实现增量计算和数据预处理。通过使用ClickHouse的分布式计算能力,可以将计算任务分配给多个节点并行处理,从而加快计算速度。同时,通过使用ClickHouse的列式存储能力,可以避免不必要的数据读取和计算,提高计算效率。

  • 利用ClickHouse的缓存机制,提高查询效率。ClickHouse支持高效的缓存机制,可以将查询结果缓存在内存中,以便更快地响应查询请求。

  • 利用ClickHouse的SQL查询语言,实现灵活的数据分析和报表生成。ClickHouse支持SQL查询语言,可以方便地进行数据分析和报表生成,同时也支持复杂查询和聚合操作,可以满足各种数据分析需求。

通过利用ClickHouse上述特性,进一步提高整个数据分析过程的效率和准确性。

五、基于ClickHouse的留存分析模型

5.1 利用ClickHouse查询速度快的特性改造离线留存图表产出方式

  • 利用ClickHouse进行实时留存查询

传统的离线留存计算通常需要借助Hadoop、Spark等大数据处理框架,需要消耗大量计算资源和时间。而利用ClickHouse进行离线留存计算,可以大大提高计算速度和效率,可以实现秒级响应和高并发查询。

具体步骤如下:

  1. 将用户行为数据导入ClickHouse;

  2. 根据查询配置数据组装留存SQL用于查询;

  3. 利用ClickHouse的高速查询功能,实时查询留存率数据。

  • 利用ClickHouse进行留存图表的产出

利用ClickHouse进行留存计算和查询后,可以通过数据可视化工具对留存数据进行图表化展示,从而更加直观地了解用户留存情况。例如:

  1. 利用数据可视化工具连接ClickHouse数据库,查看留存率数据或者通过http请求查询结果表数据;

  2. 通过数据可视化工具绘制留存图表,并进行定制化设计和样式调整。

结合hive、ClickHouse两者优点,可将架构做如下优化,对于历史较长时间日期的结果回溯进行hive查询处理,可在ClickHouse中存储的数据作为每天例行查询存储结果。

例行:是指创建一次图表每日例行执行报表任务,产出数据(例行可回溯ClickHouse中存储日期的留存数据)。

手动:是指在指定时间范围内执行,执行完成产出任务停止。

图片

图4 结合ClickHouse、hive后留存分析模型架构图

5.2 主要函数介绍

  • Retention

该函数将一组条件作为参数,类型为1到32个 UInt8 类型的参数,用来表示事件是否满足特定条件。任何条件都可以指定为参数(如 WHERE)。

除了第一个以外,条件成对适用:如果第一个和第二个是真的,第二个结果将是真的,如果第一个和第三个是真的,第三个结果将是真的,等等。

① 语法

retention(cond1, cond2, ..., cond32);

② 参数

cond — 返回 UInt8 结果(1或0)的表达式。

③ 返回值

数组为1或0。

1 — 条件满足。

0 — 条件不满足。

④ 类型

UInt8

  • ClickHouse查询SQL

  • ClickHouse即时查询留存SQL

SELECT retention_date,USER,IF(DATEDIFF('day', retention_date, NOW()) >= 1, retain0, NULL)    AS retain0,IF(DATEDIFF('day', retention_date, NOW()) >= 2, retain1, NULL)    AS retain1,IF(DATEDIFF('day', retention_date, NOW()) >= 3, retain2, NULL)    AS retain2,IF(DATEDIFF('day', retention_date, NOW()) >= 4, retain3, NULL)    AS retain3CONCAT(toString(ROUND(retain0 / USER * 100, 4)), '%')    AS ratio0,CONCAT(toString(ROUND(retain1 / retain0 * 100, 4)), '%') AS ratio1,CONCAT(toString(ROUND(retain2 / retain0 * 100, 4)), '%') AS ratio2,CONCAT(toString(ROUND(retain3 / retain0 * 100, 4)), '%') AS ratio3
FROM (SELECT b.retention_date,COUNT(DISTINCT (uid)) AS USER,SUM(ret[1])            AS retain0,SUM(ret[2])            AS retain1,SUM(ret[3])            AS retain2,SUM(ret[4])            AS retain3FROM (SELECT j.retention_date,                      uid,retention(j.day = j.retention_date,j.day = j.retention_date + INTERVAL 1 DAY,j.day = j.retention_date + INTERVAL 2 DAY,j.day = j.retention_date + INTERVAL 3 DAY,j.day = j.retention_date + INTERVAL 4 DAY) AS retFROM (SELECT b.day AS retention_date,b.uid,t.day AS DAYFROM (SELECT DAY, uidFROM abcd.test2WHERE DAY >= '开始时间'AND DAY <= '结束时间'AND event_id IN ('起始事件')GROUP BY DAY, uid ) bLEFT JOIN(SELECT uid , DAY, event_idFROM abcd.test2WHERE DAY >= '开始时间'AND DAY <= '结束时间'AND event_id IN ('回访事件')GROUP BY DAY, uid, event_id) t ON b.uid = t.uid) jGROUP BY j.retention_date, j.uid ) bGROUP BY b.retention_date)

SQL 当中返回结果含义分别为:

retention_date:留存日期

user:起始用户数

retain0:当日留存用户数

retain1:第1日留存用户数

retain2:第2日留存用户数

retain3:第3日留存用户数

ratio0:当日留存率

ratio1:第1日留存率

ratio2:第2日留存率

ratio3:第3日留存率

以上SQL含义:计算出指定时间区间内3日留存信息,可一次性查询出指定区间内的所有3日留存数据,一个sql即可查询完全。

例如:我们定了起始事件和回访事件后,去计算2022-06-01~2022-06-04的每一天的3日留存,此时,起始时间是2022-06-01,结束2022-06-04,留存天数3天。

针对此案例,在不同的日期查询数据完整性不一致,我们拿2022-06-04日和2022-06-07日两日查询举例。

第一步:针对2022-06-04日进行计算2022-06-01~2022-06-04的每一天的3日留存,执行后留存数据展示结果如下(表11)。

图片

表11 2022-06-04日计算2022-06-01~2022-06-04的每一天的3日留存数据表

第二步:针对2022-06-07日进行计算2022-06-01~2022-06-04的每一天的3日留存,执行后留存数据展示结果如下(表12)。

图片

表12 2022-06-08日计算2022-06-01~2022-06-04的每一天的3日留存数据表

趋势结果展示(图5):

图片

图5 留存分析模型趋势图

六、写在最后

本文介绍的留存模型就是数据分析工具箱的核心分析模型,使用的范围十分广泛。它通过计算用户在一段时间内的留存率,可以评估产品、服务或应用程序的用户体验和吸引力,提高用户留存率和活跃度。在实际的生产中,业务可根据自身具体需求和用户特征进行定制化设计,同时也可将通过留存分析得到的人群信息结合其他的数据分析方法进一步的深入分析。例如,从留存中得到的用户人群信息,我们可以进一步的使用路径分析的分析方法,分析用户的访问行为对于产品的影响。

数据分析的工具方法有很多,除了上面提到过得用于分析用户在应用上的访问行为的用户路径分析;也有衡量业务中关键事件之间转化效果的漏斗分析;还有事件分析、归因分析等等,他们共同组成的强大的数据分析工具箱,可以较为全面的分析用户行为的潜在特征与规律,帮助产品或者决策者作为更加可靠的决策。

————————————————————————————————————

更多相关文章:

  • 用户行为分析模型实践(一)—— 路径分析模型

  • 用户行为分析模型实践(二)—— 漏斗分析模型

  • 用户行为分析模型实践(三)——H5通用分析模型


http://www.mrgr.cn/p/68648221

相关文章

android学习笔记(二)

1、自定义View。 package com.example.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; //可以在View测量和布局完成后…

计算机网络:MAC地址 IP地址 ARP协议

计算机网络&#xff1a;MAC地址 & IP地址 & ARP协议 MAC地址IP地址ARP协议 MAC地址 如果两台主机通过一条链路通信&#xff0c;它们不需要使用地址就可以通信&#xff0c;因为连接在信道上的主机只有他们两个。换句话说&#xff0c;使用点对点信道的数据链路层不需要使…

CF1535F String Distance

\(CF1535F\ \ String\ Distance\) 题意 给 \(n\) 个长度均为 \(len\) 的字符串 \(T_1,T_2,\dots T_n\),定义 \(f(a,b)\) 为将 \(a,b\) 排序后相等的最小排序次数,若无解则为 \(1337\)(这好像是个黑客用语)。求 \[\sum _{i=1}^{n}\sum _{j=i+1}^{n}f(T_i,T_j) \]其中 \[n\tim…

连接mysql -- host is not allowed to connect to this mysql server的解决

今天通过navicat连接服务器的MySQL,报错:host is not allowed to connect to this mysql server去网上搜了一摞,有些方法不太管用,踩了点坑,在此记录下。版本:MYSQL 8.0.36, CentOS 7mysql -u root -p use mysql; select user, host from user;这时候可以看到:只允许lo…

单向循环链表的初体验

单向循环链表经过小白今天一天的学习,感觉就是在单向链表的尾结点加了一个首结点的地址,不再指向NULL,个人理解就像一群孩子围成了一个圆,头尾相连,同时多少个孩子就是多少个结点,如击鼓传花一般一个个将手上的手绢传递给下一个人,一遍下来就像是单向循环的遍历,想要到…

Modbus转Profinet网关接称重设备与工控机通讯

Modbus转Profinet网关(XD-MDPN100)是一种能够实现Modbus协议和Profinet协议之间转换的设备。Modbus转Profinet网关可提供单个或多个RS485接口,使得不同设备之间可以顺利进行通信,进一步提升了工业自动化程度。Modbus转Profinet网关接称重设备与工控机通讯Modbus转Profinet网…

逆向修改app就可以游戏充值到账?

hello ,大家好, 现在市场仍然流行着非常多的传奇类游戏私服或者其他类型的游戏私服,随着私服越来越多(很多并不合法),越来越多的人加入了破解,逆向修改,或者代充的队伍并从中获利。这里我给大家分享一下这些做代充的常规的做法,以及大家作为游戏服务器如何避坑做强校验…

Linux之安装Nginx

目录 传送门前言一、快速安装二、反向代理语法1、基本语法2、location语法1. 基本语法2. 匹配规则3. 修饰符4. 权重5. 嵌套location6. 其他指令7.案例 三、配置反向代理 传送门 SpringMVC的源码解析&#xff08;精品&#xff09; Spring6的源码解析&#xff08;精品&#xff0…

构建Python中的分布式日志系统:ELK与Fluentd的结合

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在现代软件开发中&#xff0c;日志系统是至关重要的组成部分。它们不仅用于故障排查和性能监…

Linux问题集合

Linux问题集合 1. Linux下如何定位死锁? 如果你想排查你的 Java 程序是否死锁,则可以使用 jstack 工具,它是 jdk 自带的线程堆栈分析工具。 在 Linux 下,我们可以使用 pstack + gdb 工具来定位死锁问题。 pstack 命令可以显示每个线程的栈跟踪信息(函数调用过程),它的使…

2023中国企业敏捷实践白皮书发布,免费下载

在人工智能技术飞速发展,组织面临的复杂性和多变性不断加剧的背景下,《2023中国企业敏捷实践白皮书》通过广泛的调查,洞察剧变之下,谁在逆流而上,如何逆流而上。《2023中国企业敏捷实践白皮书》发布!免费下载在人工智能技术飞速发展,组织面临的复杂性和多变性不断加剧的…

解决多线程竞争条件——临界区

如图所示,黑色表示没有获得CPU,绿色表示获得CPU,假设为单核两线程程情况。 线程1开始运行,并进入临界区,在出临界区运行过程中到了上下文切换时间。 线程2获得CPU,正常运行一段时间后需要运行至临界区代码,此时,线程1位于临界区。因为不能两个线程同时位于临界区,所以…

python爬虫—学习笔记-4

课堂内容:删除原导出文件的venv,pycham打开此文夹,重新创建本地虚拟编译器。安装依赖库,打开pycham终端输入pip install -r yilaiku.txt,安装依赖库中的库。继续安装bs4、lxml库,命令为:pip install bs4 和 pip install lxml。安装好后,pycham来到spiders目录下,新建Py…

【Hadoop】-Hive初体验[13]

Hive体验 预先确保已经完成部署Hive&#xff0c;并启动了Metastore服务 可以执行&#xff1a;bin/hive&#xff0c;进入到Hive Shell环境中&#xff0c;可以直接执行SQL语句。 创建表 create table test(id int,name string,gender string); 插入数据 INSERT INTO test val…

Linux引导过程与服务控制

Linux操作系统引导过程 排除启动类故障 服务控制及切换运行级别 优化启动过程 Linux引导过程 引导过程总览&#xff1a; 简化来说就是由开机自检 MBA引导 GRUB菜单 加载内核&#xff08;kernel&#xff09; init进程初始化等组成 Linux 操作系统的引导过程&…

SLICEM是如何将查找表配置为分布式RAM/移位寄存器的

1.首先说SliceM和SliceL如何配置为ROM的 一个SLICE包含4个六输入查找表&#xff0c;因此每个查找表就能存储64bit的数据&#xff0c;要实现128bit的ROM&#xff0c;只需要通过两个LUT就可实现&#xff0c;具体如下表: 2.如何配置成为分布式RAM SLICEM中的LUT如下图&#xff…

CSS-vminvmax单位

vmin 和 vmax 单位 vmin 是相对于视口宽度和高度中较小值进行计算,它的值为视口宽度和高度中的较小值的百分比。 例如,如果视口宽度为 800px,高度为 1000px,那么 1vmin 等于 8px(800px 的 1%)。 vmax 是相对于视口宽度和高度中较大值进行计算,它的值为视口宽度和高度中的…

Skill Check: Build an LLM Application using OCI Generative AI Service

Skill Check: Build an LLM Application using OCI Generative AI Service

循环购模式揭秘:消费即投资,边消费边赚钱的新商业模式

大家好&#xff0c;我是吴军&#xff0c;你们的私域电商管家。今天&#xff0c;我要为大家深入剖析一种新兴的商业模式——循环购模式。这个模式看似神奇&#xff0c;实则蕴含了消费返利和积分返利的智慧&#xff0c;让不少商家取得了惊人的业绩。那么&#xff0c;它究竟是如何…

前端开发攻略---实现发送手机验证码60s倒计时效果(手机号验证+按钮文字自定义显示+Vue2写法+Vue3写法)

1、演示 2、说明 1、为了便于演示&#xff0c;本示例将在3秒后就再次发送。您可以根据需要自定义此时间间隔。 2、采用最少的变量以满足需求&#xff0c;以减少内存占用。 3、不仅仅局限于按钮情况&#xff0c;也可应用于不禁用按钮的情况&#xff0c;以实现更多的扩展性。 4、…