微信小程序之分享功能

微信小程序之分享功能

小程序风口正盛,将小程序作为获客的来源之一实在合适不过,想要让小程序的获客产生裂变,那么从将小程序的数据发送出去势在必行,本文提供以下几种方案作为数据出口,达到老拉新/口碑传播的效果。

本文中所介绍的东西并没有高深的技术含量,都是一些很简单的技巧而已。

一、分享:

让用户使用小程序之后,再将它分享给好友,或者发送到朋友圈,实在太合适不过了。

1.转发给好友/群:

在小程序开发API中,发送给好友/群,可以有两种实现方式:

1)入口

a.小程序右上角自带的分享功能(…):

如果在当前页面调用wx.hideShareMenu()方法,那么右上角的分享功能将被隐藏,当然,隐藏方法与现实方法是承兑出现的,调用wx.showShareMenu()方法,可以显示该功能。

b.自定义分享按钮:<butto n open-type=’share’>分享</butto n>

以上两种方式均可实现分享功能

2)分享数据类型

不管采用以上何种方法,转发给好友的数据总归有它的数据模型,该数据模型是通过onShareAppMessage(options)返回的,也就是return一个object即可。其中,options.from可以用来判断是从自定义button打开的转发页面,还是从右上角的打开的转发页面。

以下是该object的数据模型:

如上所示,如果开发人员在onShareAppMessage(options)不进行任何处理,那么微信将会有一个默认的数据转发出去,title为当前小程序名称,path为当前页面的路径,imageUrl为当前页面的截图。根据imageUrl的定义,开发人员可以上传自定义图片,那么这个口子给了运营人员一定的发挥空间,这个问题,文章的后边会详细提及。

2.分享至朋友圈:

微信小程序目前没有直接提供方法来将小程序分享至朋友圈,不过可以采用曲线救国的方式来达到目的。

曲线救国的方式分为两步:

1.通过浏览器将希望分享的东西分享至朋友圈:

微信小程序自身没有任何入口可以进入到微信的浏览器中,那么就更加不可能让用户进入到自身操作系统中的浏览器进行分享了。

那么能否有其他的途径可以达到此目的呢?

答案是客服消息。

微信小程序本身提供客服消息是用来更好的为客户服务

小程序提供了入口,允许用户给客服发送消息,同时,也允许小程序的客服主动给用户发送消息,其中,可以发送图文链接

开发者可以在用户打开该聊天对话框时,主动给用户发送图文链接,用户点击该链接之后,将会跳转到微信的浏览器(H5)页面,该页面不同于小程序内打开的H5页面,如下图

开发者和用户对于这种样式的页面应该相当熟悉了,至此,从小程序进行分享至朋友圈的第一步完成了。

2.用户分享至朋友圈后,用户的好友通过该链接进入朋友圈

众所周知,微信目前还并未提供入口,将微信小程序直接在朋友圈进行展示,但是同样的,微信也没有禁止在朋友圈内展示小程序码,而我们通过小程序进行分享的是图文链接,那么图片自然就可以是需要分享的微信小程序码,至于文字,还可以作为运营人员的推广。

以上,就完成了从微信小程序分享至好友/好友群/朋友圈的路径。

注:小程序的二维码分两种,一种是常规的二维码,还有一种是小程序码,我们这里进行分享的是小程序码。

二、数据追踪

运营人员经常会期望知道哪些用户是自然量,哪些用户是推广量,不仅如此,他们常常期望给那些乐于分享的用户一些奖励。

那么,奖励的标准是什么?无外乎谁拉来的人多,谁就可以获得更多的奖励。开发人员需要满足运营的需求,所以需要记录每个用户通过分享获客的数量等等。

如何进行记录呢,还是老生常谈,无外乎以下几种方式:

1.简单粗暴型:

比如Uber和滴滴的获客方式,通过邀请码来进行获客。这种通过现金奖励的土豪方式不适合绝大多数的推广,而且简单粗暴,本文不再赘述。

2.数据匹配型:

现有的一些第三方推广渠道的合作方式常常都是如此,比如iOS通过用户的IDFA来进行标记用户,用户通过第三方app打开第三方渠道的短链时,由app将IDFA传给短链进行记录,当用户注册账号时,app端通过获取IDFA来和第三方渠道进行比对,如果一致,则认为是通过第三方渠道推广而来的量,最后进行结算。

微信小程序也可以模仿该方式进行记录。

上文提供了三种分享的方式,分享给好友/好友群/朋友圈,它们需要使用不同的方式来进行记录。

1)朋友圈:

分享至朋友圈是通过分享小程序码来达到分享功能的,那么想要进行数据匹配,肯定是通过小程序码来做文章了。

通过调用微信的不同的接口,可以生成类型不同的小程序码,我们调用接口:https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=ACCESS_TOKEN,具体参数如下:

关注参数scene和page即可,我们可以将用户的userid或者唯一标识放入其中,这样在其他被拉进小程序的用户打开page页面时,我们可以通过以下方式获取到分享发起者的用户唯一标识:

此时,便可以根据此唯一标识来给对应的用户发放奖励了。

2)分享至好友/群:

分享至好友/群和分享至朋友圈的内容并不一致,后者是分享图文链接,而分享至好友群的往往是小程序本身,群中的用户通过该分享可以直接进入小程序,那么如何进行数据匹配呢?

其实方法大同小异,通过查看微信小程序的api,如下:

此处的path中可以加入用户的唯一标识,接下来的流程和分享至朋友圈便是一样了。

部分运营人员期望能知道分享的群的一些信息,可以参考此文:http://news.ifeng.com/a/20170510/51071063_0.shtml

本文参考微信小程序开发文档:

1.转发:https://mp.weixin.qq.com/debug/wxadoc/dev/api/share.html

2.客服消息:https://mp.weixin.qq.com/debug/wxadoc/dev/api/custommsg/conversation.html

3.获取二维码:https://mp.weixin.qq.com/debug/wxadoc/dev/api/qrcode.html

原文:https://www.jianshu.com/p/c100d21bcc9c

微信小程序navigateBack如何带参数

wx.navigateBack({//返回

delta:1

})

方法如下:

一.

var pages = getCurrentPages();

var prevPage = pages[pages.length – 2]; //上一个页面

//直接调用上一个页面的setData()方法,把数据存到上一个页面中去

prevPage.setData({

mydata: {a:1, b:2}

})

二.

回到上一页,在data里定义mydata,然后在onshow里

var pages = getCurrentPages();

var currPage = pages[pages.length – 1]; //当前页面

console.log(currPage) ,就可以看到data里mydata的值了

小程序上传图片or文件到阿里云OSS

搞了大半天,累死了,原本在阿里云官网通过后台取签上传的方式,前端会用到lib,例子下载后无法加入到小程序中使用,后来在CSDN的一篇博文里找到了解决方案

后端get.php,callback.php从阿里云例子中取,直接用

get.php代码

<?php
    function gmt_iso8601($time) {
        $dtStr = date("c", $time);
        $mydatetime = new DateTime($dtStr);
        $expiration = $mydatetime->format(DateTime::ISO8601);
        $pos = strpos($expiration, '+');
        $expiration = substr($expiration, 0, $pos);
        return $expiration."Z";
    }

    $id= 'xxxxxxxx';          // 请填写您的AccessKeyId。
    $key= 'xxxxxxxx';     // 请填写您的AccessKeySecret。
    // $host的格式为 bucketname.endpoint,请替换为您的真实信息。
    $host = 'https://bucket名称.oss-cn-地域.aliyuncs.com/';  
    // $callbackUrl为上传回调服务器的URL,请将下面的IP和Port配置为您自己的真实URL信息。
    $callbackUrl = 'callback.php的网络路径';
    $dir = '文件保存路径';          // 用户上传文件时指定的前缀。
	
    $callback_param = array('callbackUrl'=>$callbackUrl, 
                 'callbackBody'=>'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}', 
                 'callbackBodyType'=>"application/x-www-form-urlencoded");
    $callback_string = json_encode($callback_param);

    $base64_callback_body = base64_encode($callback_string);
    $now = time();
    $expire = 30;  //设置该policy超时时间是10s. 即这个policy过了这个有效时间,将不能访问。
    $end = $now + $expire;
    $expiration = gmt_iso8601($end);


    //最大文件大小.用户可以自己设置
    $condition = array(0=>'content-length-range', 1=>0, 2=>1048576000);
    $conditions[] = $condition; 

    // 表示用户上传的数据,必须是以$dir开始,不然上传会失败,这一步不是必须项,只是为了安全起见,防止用户通过policy上传到别人的目录。
    $start = array(0=>'starts-with', 1=>'$key', 2=>$dir);
    $conditions[] = $start; 


    $arr = array('expiration'=>$expiration,'conditions'=>$conditions);
    $policy = json_encode($arr);
    $base64_policy = base64_encode($policy);
    $string_to_sign = $base64_policy;
    $signature = base64_encode(hash_hmac('sha1', $string_to_sign, $key, true));

    $response = array();
    $response['accessid'] = $id;
    $response['host'] = $host;
    $response['policy'] = $base64_policy;
    $response['signature'] = $signature;
    $response['expire'] = $end;
    $response['callback'] = $base64_callback_body;
    $response['dir'] = $dir;  // 这个参数是设置用户上传文件时指定的前缀。
    echo json_encode($response);
?>

callback.php不用改

小程序前端:

uploadAliyun(str){   //str是wx.chooseImage返回的res.tempFilePaths[0]
  var that = this;
  wx.uploadFile({
    url: 'xxxx/get.php', //你的服务器地址
    filePath: str, //要上传文件资源的路径
    name: 'headimg', //文件对应的 key,开发者在服务端可以通过这个 key 获取文件的二进制内容
    formData: {
	adminid: app.globalData.adminid  //HTTP 请求中其他额外的参数比如 用户id
    },
    success(res) {
        console.log(res)
        if(res.statusCode == 200){
          var info = JSON.parse(res.data);
          //  随机生成文件名称
          var fileRandName = Date.now() + "" + parseInt(Math.random() * 1000)
          var fileName = fileRandName + '.' + that.get_suffix(str)
          wx.uploadFile({
            url: 'https://bucket名称.oss-cn-地域.aliyuncs.com', 
            filePath: str,
            name: 'file',
            formData: {
              name: str,
              key: info.dir + fileName,
              policy: info.policy,
              signature: info.signature,
              expire : info.expire,
              success_action_status: "200",
              host: info.host,
              OSSAccessKeyId : info.accessid
            },
            success: function (res) {
              var data = res.data
              console.log(res)
              if(res.statusCode == 200){ }
            }
          })
        }
    }
   })
  },

补充get_suffix功能函数

get_suffix: function(filename) {
    var pos = filename.lastIndexOf('.')
    var suffix = ''
    if (pos != -1) {
        suffix = filename.substring(pos)
    }
    return suffix;
  },

js实现replaceAll方法

js本来有replace方法,请看w3school的说明:

  replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。

语法:

  stringObject.replace(regexp/substr,replacement)

  第一个参数为一个字符串或者一个正则表达式,第二个参数为一个字符串或者一个用于生成字符串的函数。

注意重点:

  如果 regexp 具有全局标志 g,那么 replace() 方法将替换所有匹配的子串。否则,它只替换第一个匹配子串。

实例:

var str = "dogdogdog";
var str2 = str.replace("dog","cat");
console.log(str2);

这里仅替换第一个dog字符串,输出为:catdogdog。

js中是没有replaceAll方法的,那么如何实现替换所有匹配的字符串呢,即在js中实现replaceAll方法:

1. 使用具有全局标志g的正则表达式

var str = "dogdogdog";
var str2 = str.replace(/dog/g,"cat");
console.log(str2);

实现替换全部匹配字符串,输出结果为:catcatcat。

2. 使用另一种具有全局标志g的正则表达式的定义方法

var str = "dogdogdog";
var str2 = str.replace(new RegExp("dog","gm"),"cat");
console.log(str2);

输出结果同上例。这里g表示执行全局匹配,m表示执行多次匹配。

3. 给string对象添加原型方法replaceAll()

String.prototype.replaceAll = function(s1, s2) {
    return this.replace(new RegExp(s1, "gm"), s2);
}

这样就可以像使用replace方法一样使用replaceAll方法:

var str = "dogdogdog";
var str2 = str.replaceAll("dog", "cat");
console.log(str2);

输出结果同上例。
个人推荐使用第3种方法。

原文:https://www.cnblogs.com/henuyuxiang/p/11609088.html

centos7 yum安装java环境

 centos7中安装java环境,在安装前先查看有无安装过java环境。直接运行java命令,会提示命令未找到,则是没有安装过java环境。

java[root@zixuephp ~]# java-bash: java: command not found

        也可以通过rpm命令查看:

bashrpm -qa |grep java

一、查看yum源的java包

bashyum list java*
java package list.png

二、安装java1.8 jdk软件

bashyum -y install java-1.8.0-openjdk
java sdk install.png

三、查看版本,检测是否安装成功

javajava -version
java -version.png

    如图中的会显示,表示已经安装java环境成功。

原文:https://zixuephp.net/article-406.html

MYSQL避免重复插入记录的三种方法

方案一:使用ignore关键字

如果是用主键primary或者唯一索引unique区分了记录的唯一性,避免重复插入记录可以使用:

insert ignore into table_name(email,phone,user_id) values('test9@163.com','99999','9999'),

这样当有重复记录就会忽略,执行后返回数字0,还有个应用就是复制表,避免重复记录:

insert ignore into table(name)  select  name from table2

方案二:使用Replace

replace的语法格式为:

  1. replace into table_name(col_name, …) values(…)
  2. replace into table_name(col_name, …) select …
  3. replace into table_name set col_name=value, …

算法说明:

REPLACE的运行与INSERT很相像,但是如果旧记录与新记录有相同的值,则在新记录被插入之前,旧记录被删除,即:

尝试把新行插入到表中 
当因为对于主键或唯一关键字出现重复关键字错误而造成插入失败时: 
从表中删除含有重复关键字值的冲突行 
再次尝试把新行插入到表中

旧记录与新记录有相同的值的判断标准就是:表有一个PRIMARY KEY或UNIQUE索引,否则,使用一个REPLACE语句没有意义。该语句会与INSERT相同,因为没有索引被用于确定是否新行复制了其它的行。

返回值:

REPLACE语句会返回一个数,来指示受影响的行的数目。该数是被删除和被插入的行数的和。

受影响的行数可以容易地确定是否REPLACE只添加了一行,或者是否REPLACE也替换了其它行:检查该数是否为1(添加)或更大(替换)。

示例:

eg:(phone字段为唯一索引)

  1. replace into table_name(email,phone,user_id)
  2. values(‘test569′,’99999′,’123’)

另外:在 SQL Server 中可以这样处理:

  1. if not exists (select phone from t where phone= ‘1’)
  2. insert into t(phone, update_time) values(‘1’, getdate())
  3. else
  4. update t set update_time = getdate() where phone= ‘1’

更多信息请看:http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#replace

方案三:ON DUPLICATE KEY UPDATE

如‍上所写,你也可以在INSERT INTO.....后面加上 ON DUPLICATE KEY UPDATE方法来实现。

如果您指定了ON DUPLICATE KEY UPDATE,并且插入行后会导致在一个UNIQUE索引或PRIMARY KEY中出现重复值,

则执行旧行UPDATE。例如,如果列a被定义为UNIQUE,并且包含值1,则以下两个语句具有相

同的效果:

  1. mysql>INSERT INTO table (a,b,c) VALUES (1,2,3)
  2. ->ON DUPLICATE KEY UPDATE c=c+1;
  3. mysql>UPDATE table SET c=c+1 WHERE a=1;

如果行作为新记录被插入,则受影响行的值为1;如果原有的记录被更新,则受影响行的值为2。

注释:如果列b也是唯一列,则INSERT与此UPDATE语句相当:

mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

如果a=1 OR b=2与多个行向匹配,则只有一个行被更新。通常,您应该尽量避免对带有多个唯一关键字的表使用ON DUPLICATE KEY子句。

您可以在UPDATE子句中使用VALUES(col_name)函数从INSERT…UPDATE语句的INSERT部分引用列值。

换句话说,如果没有发生重复关键字冲突,则UPDATE子句中的VALUES(col_name)可以引用被插入的

col_name的值。本函数特别适用于多行插入。VALUES()函数只在INSERT…UPDATE语句中有意义,其它时候

会返回NULL。

  1. mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
  2.  
  3. -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

本语句与以下两个语句作用相同:

  1. mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
  2. -> ON DUPLICATE KEY UPDATE c=3;
  3. mysql> INSERT INTO table (a,b,c) VALUES (4,5,6)
  4. -> ON DUPLICATE KEY UPDATE c=9;

当您使用ON DUPLICATE KEY UPDATE时,DELAYED选项被忽略。

示例: 这个例子是我在实际项目中用到的:是将一个表的数据导入到另外一个表中,数据的重复性就得考虑(如下)。 
唯一索引为:email

  1. INSERT INTO table_name1(title,first_name,last_name,email,phone,user_id,role_id,status,campaign_id)
  2.  
  3. SELECT ”,”,”,table_name2.email,table_name2.phone,
  4. NULL,NULL,’pending’,29
  5. FROM table_name2 WHERE table_name2.status = 1
  6. ON DUPLICATE KEY UPDATE table_name1.status = ‘pending’

语句的关键地方,都已高亮出来~

再贴一个例子:

  1. insert into class select * from class1
  2. ON DUPLICATE KEY UPDATE class.course = class1.course

其它关键:DELAYED 做为快速插入,并不是很关心失效性,提高插入性能。 
IGNORE 只关注主键对应记录是不存在,无则添加,有则忽略。

更多信息请看: http://dev.mysql.com/doc/refman/5.1/zh/sql-syntax.html#insert

特别说明:在MYSQL中UNIQUE 索引将会对null字段失效,也就是说(a字段上建立唯一索引):

  1. insert into test(a) values(null)
  2. insert into test(a) values(null)

是可以重复插入的(联合唯一索引也一样)。

原文:https://www.cnblogs.com/zhuyeshen/p/11643079.html

php vs js中判断一个字符串包含另一个字符串的方法

PHP

第一种方法:用php的strpos() 函数判断字符串中是否包含某字符串的方法

if(strpos('www.jb51.net','jb51') !== false){
echo '包含jb51';
}else{
echo '不包含jb51';
}

第二种 使用了explode

用explode进行判断PHP判断字符串的包含代码如下:

<?php 
$name = "001x.gif"; 
$pan = "x"; 
$con = explode($pan,$name); 
if (count($con)>1): 
echo $name."中包含".$pan; 
else: 
echo $name."中没有包含".$pan; 
endif; 
?> 

第三种strstr

strstr() 函数搜索一个字符串在另一个字符串中的第一次出现。
该函数返回字符串的其余部分(从匹配点)。如果未找到所搜索的字符串,则返回 false。

代码如下:

<?php
  /*如手册上的举例*/
  $email = 'user@example.com';
  $domain = strstr($email, '@');
  echo $domain;
  // prints @example.com
?>

第四种、stristr

stristr() 函数查找字符串在另一个字符串中第一次出现的位置。
如果成功,则返回字符串的其余部分(从匹配点)。如果没有找到该字符串,则返回 false。

它和strstr的使用方法完全一样.唯一的区别是stristr不区分大小写.

JS

String对象的方法

方法一: indexOf()   (推荐)

var str = "123";
console.log(str.indexOf("3") != -1 );  // true
//indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。如果要检索的字符串值没有出现,则该方法返回 -1。

方法二: search() 

var str = "123";
console.log(str.search("3") != -1 );  // true
//search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。如果没有找到任何匹配的子串,则返回 -1。

方法三:match()

var str = "123";
var reg = RegExp(/3/);
if(str.match(reg)){
    // 包含        
}
//match() 方法可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配。

RegExp 对象方法

方法四:test() 

var str = "123";
var reg = RegExp(/3/);
console.log(reg.test(str)); // true
//test() 方法用于检索字符串中指定的值。返回 true 或 false。

方法五:exec()

var str = "123";
var reg = RegExp(/3/);
if(reg.exec(str)){
    // 包含        
}
//exec() 方法用于检索字符串中的正则表达式的匹配。返回一个数组,其中存放匹配的结果。如果未找到匹配,则返回值为 null。

原文:php-https://www.jb51.net/article/8632.htm

JS-https://www.cnblogs.com/rxbook/p/11820720.html

微信小程序弹窗提示怎么写

第一种:弹出提示框,可以选择确定或者取消。

代码:

wx.showModal({
 title: '提示',
 content: '这是一个模态弹窗',
 success: function (res) {
   if (res.confirm) {//这里是点击了确定以后
     console.log('用户点击确定')
   } else {//这里是点击了取消以后
     console.log('用户点击取消')
   }
 }
})

第二种:不带确定和取消的,直接提示成功

代码:

wx.showToast({
 title: '成功',
 icon: 'success',
 duration: 2000//持续的时间
})

第三种:提示等待中…

代码:

wx.showToast({
 title: '等待...',
 icon: 'loading',
 duration: 2000//持续的时间
})

第四种:提示文字,没有任何图标效果,但是文字可以写的很多。

代码:

wx.showToast({
 title: '这里面可以写很多的文字,比其他的弹窗都要多!',
 icon: 'none',
 duration: 2000//持续的时间
})

第五种:弹窗提示选择,例如选择ABCD那种

代码:

wx.showActionSheet({
 itemList: ['A', 'B', 'C'],
 success: function (res) {
   if (!res.cancel) {
     console.log(res.tapIndex)//这里是点击了那个按钮的下标
   }
 }
})


第六种:多用于页面提示加载

代码:

<loading hidden="{{hidden}}">
       加载中...
</loading>

hidden有两个值:false和true

原文:https://jingyan.baidu.com/article/456c463b38ca900a5831449a.html

linux系统中的i386/i686和x86_64有什么区别

Linux的的版本众多,包括服务器版本、桌面版本等,在下载安装镜像时候总会有i386/i686和x86_64这样的区别,带着疑问查了一下相关资料:

(1)参考一:http://blog.csdn.net/yandaqijian/article/details/41748759?locationNum=14点击打开链接

(2)参考二:http://blog.csdn.net/yandaqijian/article/details/41748599点击打开链接

总结来说:i386对应的是32位系统、而i686是i386的一个子集,i686仅对应P6及以上级别的CPU,i386则广泛适用于80386以上的各种CPU;x86_64主要是64位系统。

微信小程序页面停留时间统计

近来在研究微信小程用户是否在使用小程序或者查看用户在小程序停留的时间,无意中在git上找到了相关的解决问题方法,希望正在开发这个功能的的你,能帮助你解决!

但是好像有

收到一个需求,要统计一个用户在我们小程序的每个页面的停留时间。

看了下现成的API,除了这个好像也没有别的可以用:https://mp.weixin.qq.com/debug/wxadoc/dev/api/analysis-visit.html#访问趋势

这个里面貌似有页面停留时间的数据,

参数说明ref_date时间,如:”20170306-20170312″session_cnt打开次数(自然周内汇总)visit_pv访问次数(自然周内汇总)visit_uv访问人数(自然周内去重)visit_uv_new新用户数(自然周内去重)stay_time_uv人均停留时长 (浮点型,单位:秒)stay_time_session次均停留时长 (浮点型,单位:秒)visit_depth平均访问深度 (浮点型)

但是好像有查询时间限制,只能查询一天的数据。毕竟小程序数据很大,估计也是怕数据量太大查询慢吧。

算了,自己写一个吧,

初步想法,在页面的onShow事件里面,打一个开始的时间戳,然后在onHide里面再弄一个时间戳,两个一减,然后把得出来的数据,一提交,齐活。

BUT~,尼玛,onShowonHide不仅在页面切换的时候会触发,小程序切换到后台和回到前台,也会触发,这就有干扰了。

但是在app.js里面的onShowonHide事件只在小程序前后台切换的时候才会触发,不会在页面切换的时候触发,利用这点,把前后台切换排除掉,只在页面切换的时候,上报页面停留时间就好了

app.js里面,初始化以下三个状态,

globalData: { 
    firstIn:1,
    onShow: 0, 
    onHide: 0
}

onShowonHide的值默认为0,当小程序进入后台或者返回前台的时候,给这两个值变为1,用来告诉页面,刚才的切换是前后台切换,不是页面切换,不用上报页面停留时间。代码如下:

依旧是在app.js里面

onShow(){ 
    if(this.globalData.firstIn){
        this.globalData.firstIn = 0; 
    } else{ 
        this.globalData.onShow = 1; 
    } 
}, 
onHide(){ 
    this.globalData.onHide = 1; 
}

里面的firstIn表示是不是第一次进入小程,因为第一次进入的时候也会触发onShow(相当于从后台切换到前台了),要把这个也排除在外。默认是第一次进入,进入之后就把这个值置为0

OK,app.js准备好了,然后看下具体页面的,

在页面里面,先声明两个变量,一个startTime,一个endTime分别来存储用户进入页面的时间和离开的时间

var startTime,
      endTime,
      app = getApp();
Page({
    onShow(){
        setTimeout(function () {
            if (app.globalData.onShow) {
                app.globalData.onShow = 0;
                console.log("demo前后台切换之切到前台")
            }
            else {
                console.log("demo页面被切换显示")
                startTime = +new Date();
            }
        }, 100)
    },
    onHide(){
        setTimeout(function () {
            if (app.globalData.onHide) {
                app.globalData.onHide = 0;
                console.log("还在当前页面活动")
            }
            else {
                endTime = +new Date();
                console.log("demo页面停留时间:" + (endTime - startTime))
                var stayTime = endTime - startTime;
               //这里获取到页面停留时间stayTime,然后了可以上报了
            }
        }, 100)
    }
})

有几个页面要统计的,就把这几个页面都加一下。

嫌麻烦的话,可以修改一下Page方法,默认自带onShowonHide,然后如果外面有传入的话,可以合并。页面在使用的时候,直接用这个心的Page,就不用每个页面都onHideonShow了,这里就不上具体的代码了。

关于setTimeout的说明:

页面的onShowonHide会在app.jsonShowonHide之前执行,加个延迟,放到后面执行,这样每次都可以先检测是页面切换还是前后台切换,然后再去做对应的逻辑,不然就反了。

原文:https://developers.weixin.qq.com/community/develop/article/doc/000ac4169107e8e1a12b4ff6256813

参考地址:https://github.com/ireeoome/reeoome/issues/3