HBuilderX

HBuilderX

极客开发工具
uni-app

uni-app

开发一次,多端覆盖
uniCloud

uniCloud

云开发平台
HTML5+

HTML5+

增强HTML5的功能体验
MUI

MUI

上万Star的前端框架

常用的正则表达式

更全的正则表达式请访问 最全的常用正则表达式大全
由于工作需要,需要用到很多正则表达式来进行相关的验证,下面是一些常用的正则表达式,如有错误请及时指正:

  1. 判断是否为纯数字(比如电话等)
    /^\d+$/ ,
    例: /^\d+$/.test(str) ;
  2. 判断字符串中是否包含数字(比如姓名等)
    /[0-9]/,
    例:/[0-9]/.test(str);
  3. 判断字符串中是否包含特殊字符(比如姓名等)
    /[~!@#\$%\^\&\*\(\)_\+<>\?:"\{\},\.\\\/;'\[\]]/im, 例:/[~!@#\$%\^\&*()_+<>\?:"{},.\\/;'[]]/im.test(str);(注:此正则表达式并不能包含所有的特殊字符,根据实际情况而定)
  4. 判断电话号码的位数(包含7位和11位)
    /(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$/,
    例: /(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$/.test(str);
  5. 判断邮箱格式是否正确
    /^([a-zA-Z0-9.-])+\@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/,
    例:/^([a-zA-Z0-9
    .-])+\@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/.test(str);
  6. 判断是否只包含数字和字母:
    /^[A-Za-z0-9]+$/。

正则表达式——古老而又强大的文本处理工具。仅用一段简短的表达式语句,就能快速地实现一个复杂的业务逻辑。掌握正则表达式,让你的开发效率有一个质的飞跃。

正则表达式经常被用于字段或任意字符串的校验,比如下面这段校验基本日期格式的JavaScript代码:

var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/;
var r = fieldValue.match(reg);
if(r==null)alert('Date format error!');

1、校验密码强度
密码的强度必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间

^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$

2、校验中文
字符串只能是中文

^[\u4e00-\u9fa5]{0,}$

3、由数字,26个英文字母或下划线组成的字符串

^\w+$

4、校验E-Mail 地址

[\w!#$%&'+/=?^_`{|}~-]+(?:\.[\w!#$%&'+/=?^_`{|}~-]+)@(?:[\w](?:[\w-][\w])?\.)+\w?

5、校验身份证号码
15位:

^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$

18位:

^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$

6、校验日期
“yyyy-mm-dd“ 格式的日期校验,已考虑平闰年

^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$

7、校验金额
金额校验,精确到2位小数

^[0-9]+(.[0-9]{2})?$

8、校验手机号
下面是国内 13、15、18开头的手机号正则表达式

^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

9、判断IE的版本

^.MSIE 5-8?(?!.Trident\/[5-9]\.0).*$

10、校验IP-v4地址

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

11、校验IP-v6地址

(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

12、检查URL的前缀

if (!s.match(/^[a-zA-Z]+:\/\//)){
s = 'http://' + s;}

13、提取URL链接

^(f|ht){1}(tp|tps):\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?

14、文件路径及扩展名校验

^([a-zA-Z]\:|\\)\\([^\\]+\\)[^\/:?"<>|]+\.txt(l)?$

15、提取Color Hex Codes

^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$

16、提取网页图片

\< [img][^\\>][src] = [\"\']{0,1}([^\"\'\ >]*)

17、提取页面超链接

(<a\s(?!.\brel=)[^>])(href="https?:\/\/)((?!(?:(?:www\.)?'.implode('|(?:www\.)?', $follow_list).'))[^"]+)"((?!.\brel=)[^>])(?:[^>])>

18、查找CSS属性

^\s[a-zA-Z\-]+\s[:]{1}\s[a-zA-Z0-9\s.#]+[;]{1}

19、抽取注释

<!--(.*?)-->

20、匹配HTML标签

<\/?\w+((\s+\w+(\s=\s(?:".?"|'.?'|[\^'">\s]+))?)+\s|\s)\/?>

正则表达式 Cheat Sheet,可以用来快速查找相关语法

文/技匠(简书签约作者)
原文链接:http://www.jianshu.com/p/e7bb97218946

https://mp.weixin.qq.com/s?__biz=MzAxNjM3NzM5Mg==&mid=2453281996&idx=1&sn=3fb5bdc7c3d1cc1259aa0f453253e459&chksm=8c3b0f93bb4c8685e6cebf474ca3eb4f562e4dfe8c954e8cd2293cf2836107f2ce16ebbeb4b8&scene=0&key=1509e3bfc22f49824b0a4028c5f7432cbc673973567dc74eec078b2d8fac9e8bb5d50d85c3627b8efbf2205e1fb2034c20faf1639bf33b76a22885ae82de62daa81f7ae43d4b63b3d25f7d4c9aadda54&ascene=0&uin=MTYzOTA2OTA0MA%3D%3D&devicetype=iMac14%2C3+OSX+OSX+10.12.2+build(16C67)&version=12010210&nettype=WIFI&fontScale=100&pass_ticket=l7XDNuCDiHDNdGhimfV5LgEMsqKPsuNBtmPpkQs9Iuq0lmwWrQs1oURNiyKZNKaK

继续阅读 »

更全的正则表达式请访问 最全的常用正则表达式大全
由于工作需要,需要用到很多正则表达式来进行相关的验证,下面是一些常用的正则表达式,如有错误请及时指正:

  1. 判断是否为纯数字(比如电话等)
    /^\d+$/ ,
    例: /^\d+$/.test(str) ;
  2. 判断字符串中是否包含数字(比如姓名等)
    /[0-9]/,
    例:/[0-9]/.test(str);
  3. 判断字符串中是否包含特殊字符(比如姓名等)
    /[~!@#\$%\^\&\*\(\)_\+<>\?:"\{\},\.\\\/;'\[\]]/im, 例:/[~!@#\$%\^\&*()_+<>\?:"{},.\\/;'[]]/im.test(str);(注:此正则表达式并不能包含所有的特殊字符,根据实际情况而定)
  4. 判断电话号码的位数(包含7位和11位)
    /(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$/,
    例: /(\d{11})|^((\d{7,8})|(\d{4}|\d{3})-(\d{7,8})|(\d{4}|\d{3})-(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1})|(\d{7,8})-(\d{4}|\d{3}|\d{2}|\d{1}))$/.test(str);
  5. 判断邮箱格式是否正确
    /^([a-zA-Z0-9.-])+\@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/,
    例:/^([a-zA-Z0-9
    .-])+\@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/.test(str);
  6. 判断是否只包含数字和字母:
    /^[A-Za-z0-9]+$/。

正则表达式——古老而又强大的文本处理工具。仅用一段简短的表达式语句,就能快速地实现一个复杂的业务逻辑。掌握正则表达式,让你的开发效率有一个质的飞跃。

正则表达式经常被用于字段或任意字符串的校验,比如下面这段校验基本日期格式的JavaScript代码:

var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/;
var r = fieldValue.match(reg);
if(r==null)alert('Date format error!');

1、校验密码强度
密码的强度必须包含大小写字母和数字的组合,不能使用特殊字符,长度在8-10之间

^(?=.\d)(?=.[a-z])(?=.*[A-Z]).{8,10}$

2、校验中文
字符串只能是中文

^[\u4e00-\u9fa5]{0,}$

3、由数字,26个英文字母或下划线组成的字符串

^\w+$

4、校验E-Mail 地址

[\w!#$%&'+/=?^_`{|}~-]+(?:\.[\w!#$%&'+/=?^_`{|}~-]+)@(?:[\w](?:[\w-][\w])?\.)+\w?

5、校验身份证号码
15位:

^[1-9]\d{7}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}$

18位:

^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X)$

6、校验日期
“yyyy-mm-dd“ 格式的日期校验,已考虑平闰年

^(?:(?!0000)[0-9]{4}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1[0-9]|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[0-9]{2}(?:0[48]|[2468][048]|[13579][26])|(?:0[48]|[2468][048]|[13579][26])00)-02-29)$

7、校验金额
金额校验,精确到2位小数

^[0-9]+(.[0-9]{2})?$

8、校验手机号
下面是国内 13、15、18开头的手机号正则表达式

^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$

9、判断IE的版本

^.MSIE 5-8?(?!.Trident\/[5-9]\.0).*$

10、校验IP-v4地址

\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b

11、校验IP-v6地址

(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))

12、检查URL的前缀

if (!s.match(/^[a-zA-Z]+:\/\//)){
s = 'http://' + s;}

13、提取URL链接

^(f|ht){1}(tp|tps):\/\/([\w-]+\.)+[\w-]+(\/[\w- ./?%&=]*)?

14、文件路径及扩展名校验

^([a-zA-Z]\:|\\)\\([^\\]+\\)[^\/:?"<>|]+\.txt(l)?$

15、提取Color Hex Codes

^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$

16、提取网页图片

\< [img][^\\>][src] = [\"\']{0,1}([^\"\'\ >]*)

17、提取页面超链接

(<a\s(?!.\brel=)[^>])(href="https?:\/\/)((?!(?:(?:www\.)?'.implode('|(?:www\.)?', $follow_list).'))[^"]+)"((?!.\brel=)[^>])(?:[^>])>

18、查找CSS属性

^\s[a-zA-Z\-]+\s[:]{1}\s[a-zA-Z0-9\s.#]+[;]{1}

19、抽取注释

<!--(.*?)-->

20、匹配HTML标签

<\/?\w+((\s+\w+(\s=\s(?:".?"|'.?'|[\^'">\s]+))?)+\s|\s)\/?>

正则表达式 Cheat Sheet,可以用来快速查找相关语法

文/技匠(简书签约作者)
原文链接:http://www.jianshu.com/p/e7bb97218946

https://mp.weixin.qq.com/s?__biz=MzAxNjM3NzM5Mg==&mid=2453281996&idx=1&sn=3fb5bdc7c3d1cc1259aa0f453253e459&chksm=8c3b0f93bb4c8685e6cebf474ca3eb4f562e4dfe8c954e8cd2293cf2836107f2ce16ebbeb4b8&scene=0&key=1509e3bfc22f49824b0a4028c5f7432cbc673973567dc74eec078b2d8fac9e8bb5d50d85c3627b8efbf2205e1fb2034c20faf1639bf33b76a22885ae82de62daa81f7ae43d4b63b3d25f7d4c9aadda54&ascene=0&uin=MTYzOTA2OTA0MA%3D%3D&devicetype=iMac14%2C3+OSX+OSX+10.12.2+build(16C67)&version=12010210&nettype=WIFI&fontScale=100&pass_ticket=l7XDNuCDiHDNdGhimfV5LgEMsqKPsuNBtmPpkQs9Iuq0lmwWrQs1oURNiyKZNKaK

收起阅读 »

mui下拉模块安卓有问题

共用模板,下拉刷新

安卓机父子webview,子webview用上下拉刷新模块后,无法往下滑动,且下拉距离非常短,不够正在刷新那个div的高度;
mui("#refresh").scroll({
scrollY: true, //是否竖向滚动
scrollX: false, //是否横向滚动
startX: 0, //初始化时滚动至x
startY: 0, //初始化时滚动至y
indicators: false, //是否显示滚动条
deceleration: 0.0005, //阻尼系数,系数越小滑动越灵敏
bounce: true //是否启用回弹
});
mui.init({
pullRefresh: {
container: "#refresh", //下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等
down: {
height: 50, //可选,默认50.触发下拉刷新拖动距离,
auto: false, //可选,默认false.自动下拉刷新一次
contentdown: "下拉可以刷新", //可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
contentover: "释放立即刷新", //可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
contentrefresh: "正在刷新...", //可选,正在刷新状态时,下拉刷新控件上显示的标题内容
callback: pullupfresh //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
}
}
});

        function pullupfresh() {  
            setTimeout(function() {  
                alert("shuaxin");  
                mui('#refresh').pullRefresh().endPulldownToRefresh();  
            })  
        }  

这些都写了,ios没问题,就安卓的无法往下滑动。

继续阅读 »

安卓机父子webview,子webview用上下拉刷新模块后,无法往下滑动,且下拉距离非常短,不够正在刷新那个div的高度;
mui("#refresh").scroll({
scrollY: true, //是否竖向滚动
scrollX: false, //是否横向滚动
startX: 0, //初始化时滚动至x
startY: 0, //初始化时滚动至y
indicators: false, //是否显示滚动条
deceleration: 0.0005, //阻尼系数,系数越小滑动越灵敏
bounce: true //是否启用回弹
});
mui.init({
pullRefresh: {
container: "#refresh", //下拉刷新容器标识,querySelector能定位的css选择器均可,比如:id、.class等
down: {
height: 50, //可选,默认50.触发下拉刷新拖动距离,
auto: false, //可选,默认false.自动下拉刷新一次
contentdown: "下拉可以刷新", //可选,在下拉可刷新状态时,下拉刷新控件上显示的标题内容
contentover: "释放立即刷新", //可选,在释放可刷新状态时,下拉刷新控件上显示的标题内容
contentrefresh: "正在刷新...", //可选,正在刷新状态时,下拉刷新控件上显示的标题内容
callback: pullupfresh //必选,刷新函数,根据具体业务来编写,比如通过ajax从服务器获取新数据;
}
}
});

        function pullupfresh() {  
            setTimeout(function() {  
                alert("shuaxin");  
                mui('#refresh').pullRefresh().endPulldownToRefresh();  
            })  
        }  

这些都写了,ios没问题,就安卓的无法往下滑动。

收起阅读 »

移动应用与HTML5产业峰会召开啦,HTML5 中国产业联盟将在大会上举行挂靠于工信部通信研究院标准所仪式,欢迎踊跃报名

规范 联盟 HTML5+

由工业和信息化部、中国信息通信研究院、移动智能终端技术创新与产业联盟举办的峰会、W3C (中国)及HTML5 中国产业联盟共同承办的“移动应用与HTML5产业”分论坛邀你参加!

会议亮点

  • HTML5 中国产业联盟挂靠工信部仪式
  • HTML5行业的最新动态,标准和应用的发展研讨
  • 小程序及流应用等动态App会对移动互联网发展产生怎样的影响,开发者、流量平台、手机厂商、从业人士都怎么看。

时间

10月28日(9:00-12:00)

地点

北京国家会议中心(鸟巢旁)

会场位置(北京)

会议日程

扫描二维码,选择分会场四免费报名参会:


风雨雾霾都无阻,我们等你!!

继续阅读 »

由工业和信息化部、中国信息通信研究院、移动智能终端技术创新与产业联盟举办的峰会、W3C (中国)及HTML5 中国产业联盟共同承办的“移动应用与HTML5产业”分论坛邀你参加!

会议亮点

  • HTML5 中国产业联盟挂靠工信部仪式
  • HTML5行业的最新动态,标准和应用的发展研讨
  • 小程序及流应用等动态App会对移动互联网发展产生怎样的影响,开发者、流量平台、手机厂商、从业人士都怎么看。

时间

10月28日(9:00-12:00)

地点

北京国家会议中心(鸟巢旁)

会场位置(北京)

会议日程

扫描二维码,选择分会场四免费报名参会:


风雨雾霾都无阻,我们等你!!

收起阅读 »

js,判断对象的类型,typeof,constructor

js判断对象的类型

javascript,判断对象的类型,typeof,constructor

用typeof操作符判断对象类型:(红色文字,是上面一句代码的执行结果)

用对象的构造函数属性(constructor),来判断对象的类型:

区别:

constructor判断对象的类型,会比typeof更精确,constructor能获取一些复杂对象的类型,typeof做不到。

下面有一段程序示例:

代码示例:

<script type="text/javascript" charset="utf-8">

var s='a string';

var arr=[];

var obj=new Object();

if(typeof s=='string'){

console.log( "typeof s=='string' true"); //true

}

//打开浏览器的控制台,可以看到此代码的输出

console.log( 's.constructor==String :'+ (s.constructor==String) );

console.log( 'arr.constructor==Array :'+ (arr.constructor==Array) );

console.log( 'obj.constructor==Object :'+ (obj.constructor==Object) );

//复杂类型的对象,判断其类型

function User(name , age){

this.name=name;

this.age=age;

}

var u=new User();

console.log( 'typeof u :'+typeof u ); //输出object //显然,使用typeof判断复杂类型的对象,就失效了,但使用constructor就可以获取其真实类型

console.log( 'u.constructor.name :'+u.constructor.name );

</script>

继续阅读 »

js判断对象的类型

javascript,判断对象的类型,typeof,constructor

用typeof操作符判断对象类型:(红色文字,是上面一句代码的执行结果)

用对象的构造函数属性(constructor),来判断对象的类型:

区别:

constructor判断对象的类型,会比typeof更精确,constructor能获取一些复杂对象的类型,typeof做不到。

下面有一段程序示例:

代码示例:

<script type="text/javascript" charset="utf-8">

var s='a string';

var arr=[];

var obj=new Object();

if(typeof s=='string'){

console.log( "typeof s=='string' true"); //true

}

//打开浏览器的控制台,可以看到此代码的输出

console.log( 's.constructor==String :'+ (s.constructor==String) );

console.log( 'arr.constructor==Array :'+ (arr.constructor==Array) );

console.log( 'obj.constructor==Object :'+ (obj.constructor==Object) );

//复杂类型的对象,判断其类型

function User(name , age){

this.name=name;

this.age=age;

}

var u=new User();

console.log( 'typeof u :'+typeof u ); //输出object //显然,使用typeof判断复杂类型的对象,就失效了,但使用constructor就可以获取其真实类型

console.log( 'u.constructor.name :'+u.constructor.name );

</script>

收起阅读 »

在用的时候 总是跳出这个窗口详细是怎么回事?

发生了错误。请参阅错误日志以了解更多详细信息。
org.eclipse.ui.internal.Workbench.saveMemen()V

发生了错误。请参阅错误日志以了解更多详细信息。
org.eclipse.ui.internal.Workbench.saveMemen()V

IOS开发者证书信息有误

原来都可以的,最近没打包,今天用原有的配置上传ios包云端打包,
客户端这边校验都通过了,上传后云端提示开发者证书信息有误,
我的打包信息都是直接用的原来的,什么都没改,这个证书之前打包也都正常,
麻烦帮忙看下,谢谢!

继续阅读 »

原来都可以的,最近没打包,今天用原有的配置上传ios包云端打包,
客户端这边校验都通过了,上传后云端提示开发者证书信息有误,
我的打包信息都是直接用的原来的,什么都没改,这个证书之前打包也都正常,
麻烦帮忙看下,谢谢!

收起阅读 »

不会app开发,只要学习就行,快来东翌学院学习app开发吧

mui

混合app开发课程包含html,css,html5,css3,js,ui,mui,h5+,csatapp.js,php,mysql,混合开发app技术
react native app开发课程,HTML5,CSS3,Javascript,ECMAscript6,php,mysql,React Native课程。
联系qq:2971611409 进入教室

继续阅读 »

混合app开发课程包含html,css,html5,css3,js,ui,mui,h5+,csatapp.js,php,mysql,混合开发app技术
react native app开发课程,HTML5,CSS3,Javascript,ECMAscript6,php,mysql,React Native课程。
联系qq:2971611409 进入教室

收起阅读 »

HTML5的rtsp直播测试。大家都来试试,看看HTML5能兼容到什么程度了!

HTML5 video

最近也要用到RTSP。试了一下HTML5的video,可以正常播放。
不过自已要播放海康的NVR的RTSP流,可能是视频编码问题吧,无法正常播。
测试代码:
<video style="transform: rotate(0deg);" id="v1" controls="controls" onmouseover="this.play()" height="600" width="800">
<source src="rtsp://218.204.223.237:554/live/1/67A7572844E51A64/f68g2mj7wjua3la7.sdp">
html5 video
</video>

用手机打开下面地址:http://pass.wswifi.cn/1/1.html
测试过QQ浏览器,微信浏览器,华为6p自带浏览器。都通过!
大家都来测试一下,反应一下测试结果!
目前,海康的NVR还没搞定。

继续阅读 »

最近也要用到RTSP。试了一下HTML5的video,可以正常播放。
不过自已要播放海康的NVR的RTSP流,可能是视频编码问题吧,无法正常播。
测试代码:
<video style="transform: rotate(0deg);" id="v1" controls="controls" onmouseover="this.play()" height="600" width="800">
<source src="rtsp://218.204.223.237:554/live/1/67A7572844E51A64/f68g2mj7wjua3la7.sdp">
html5 video
</video>

用手机打开下面地址:http://pass.wswifi.cn/1/1.html
测试过QQ浏览器,微信浏览器,华为6p自带浏览器。都通过!
大家都来测试一下,反应一下测试结果!
目前,海康的NVR还没搞定。

收起阅读 »

跨webview弹出popover菜单及遮罩层

弹出菜单

在需要弹出菜单的父页面添加代码

        var floatw = null;  
        mui.plusReady(function() {  
            ws = plus.webview.currentWebview();  
            floatw = plus.webview.create("menu.html", "menu", {  
                background: 'transparent',  
                zindex: 10,  
            });  
        })  

        // 创建悬浮窗口  
        function floatWebview() {  
            if(floatw) { // 避免快速多次点击创建多个窗口  
                floatw.show("fade-in");  
            } else {  
                floatw = plus.webview.create("menu.html", "menu", {  
                    background: 'transparent',  
                    zindex: 10,  
                });  
                floatw.show("fade-in");  
            }  
        }  

//触发弹出菜单事件floatWebview();

然后将附件加入到项目中

这是我写的效果最好的一个

继续阅读 »

在需要弹出菜单的父页面添加代码

        var floatw = null;  
        mui.plusReady(function() {  
            ws = plus.webview.currentWebview();  
            floatw = plus.webview.create("menu.html", "menu", {  
                background: 'transparent',  
                zindex: 10,  
            });  
        })  

        // 创建悬浮窗口  
        function floatWebview() {  
            if(floatw) { // 避免快速多次点击创建多个窗口  
                floatw.show("fade-in");  
            } else {  
                floatw = plus.webview.create("menu.html", "menu", {  
                    background: 'transparent',  
                    zindex: 10,  
                });  
                floatw.show("fade-in");  
            }  
        }  

//触发弹出菜单事件floatWebview();

然后将附件加入到项目中

这是我写的效果最好的一个

收起阅读 »

mui页面间跳转并且传值以及fire()方法

刚开始学mui时,页面跳转传值无疑是很多初学者遇到的难题。这里分享一个我自己调试好了的两个页面间操作:  
场景是index.html页面跳转至a.html页面并且传值(包括预加载参数跟fire()带的参数)。注意,这里用到的方法是很多方法中的一种,有需要改进的地方,请多多指教。我也是初学O(∩_∩)O。  
【index.htm页面代码如下】:  
<!DOCTYPE html>  
<html>  

    <head>  

        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <script src="js/mui.min.js"></script>  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
        </script>  
    </head>  

    <body>  
        <div class="mui-content">  
            <button type="button" id="bbtn" class="mui-btn mui-btn-blue">a.html</button>  
            <div id="sss">....</div>  
        </div>  
    </body>  
    <script>  
        var apage = null;  
        mui.plusReady(function() {  
            mui.preload({  
                url: "a.html",  
                id: "a.html", //默认使用当前页面的url作为id  
                styles: {}, //窗口参数  
                extras: {  
                    idd: "mui.preload预加载页面了"  
                } //自定义扩展参数  
            });  

            document.getElementById("bbtn").addEventListener('tap', function() {  
                if(apage == null) {  
                    apage = plus.webview.getWebviewById("a.html");  
                }  
                mui.fire(apage, 'hahah', {  
                    idd: "ID是我"  
                });  
                apage.show();  
            })  
        });  
    </script>  
    <script>  
        document.addEventListener('backIndexPage', function(ee) {  
            document.getElementById("sss").innerText = ee.detail.str;  
        })  
    </script>  

</html>  

【a.html页面代码如下】:  
<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
        </script>  
    </head>  

    <body>  
        <div class="mui-content">  
            <button type="button" id="anniu">返回</button>  
            <div id="ggg">....</div>  
            <div id="ggg1">....</div>  
        </div>  
    </body>  
    <script>  
        document.addEventListener('hahah', function(e) {  
            var ppg = plus.webview.currentWebview();  
            //var ppg = plus.webview.getWebviewById('a.html');  
            document.getElementById("ggg").innerText = "fire事件参数:" + e.detail.idd;  
            document.getElementById("ggg1").innerText = "页面预加载参数:" + ppg.idd;  
        })  

        document.getElementById("anniu").addEventListener('tap',function(){  
            //var indexPage=plus.webview.getWebviewById('index.html');  
            var indexPage=plus.webview.getLaunchWebview();//获取首页对象  
            console.log(indexPage);  
            mui.fire(indexPage,'backIndexPage',{str:"我回来了!"});  
            mui.back();  
        })  
    </script>  

</html>  
继续阅读 »
刚开始学mui时,页面跳转传值无疑是很多初学者遇到的难题。这里分享一个我自己调试好了的两个页面间操作:  
场景是index.html页面跳转至a.html页面并且传值(包括预加载参数跟fire()带的参数)。注意,这里用到的方法是很多方法中的一种,有需要改进的地方,请多多指教。我也是初学O(∩_∩)O。  
【index.htm页面代码如下】:  
<!DOCTYPE html>  
<html>  

    <head>  

        <meta charset="utf-8">  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <title></title>  
        <script src="js/mui.min.js"></script>  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <script type="text/javascript" charset="utf-8">  
            mui.init();  
        </script>  
    </head>  

    <body>  
        <div class="mui-content">  
            <button type="button" id="bbtn" class="mui-btn mui-btn-blue">a.html</button>  
            <div id="sss">....</div>  
        </div>  
    </body>  
    <script>  
        var apage = null;  
        mui.plusReady(function() {  
            mui.preload({  
                url: "a.html",  
                id: "a.html", //默认使用当前页面的url作为id  
                styles: {}, //窗口参数  
                extras: {  
                    idd: "mui.preload预加载页面了"  
                } //自定义扩展参数  
            });  

            document.getElementById("bbtn").addEventListener('tap', function() {  
                if(apage == null) {  
                    apage = plus.webview.getWebviewById("a.html");  
                }  
                mui.fire(apage, 'hahah', {  
                    idd: "ID是我"  
                });  
                apage.show();  
            })  
        });  
    </script>  
    <script>  
        document.addEventListener('backIndexPage', function(ee) {  
            document.getElementById("sss").innerText = ee.detail.str;  
        })  
    </script>  

</html>  

【a.html页面代码如下】:  
<!doctype html>  
<html>  

    <head>  
        <meta charset="UTF-8">  
        <title></title>  
        <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />  
        <link href="css/mui.min.css" rel="stylesheet" />  
        <script src="js/mui.min.js"></script>  
        <script type="text/javascript">  
            mui.init();  
        </script>  
    </head>  

    <body>  
        <div class="mui-content">  
            <button type="button" id="anniu">返回</button>  
            <div id="ggg">....</div>  
            <div id="ggg1">....</div>  
        </div>  
    </body>  
    <script>  
        document.addEventListener('hahah', function(e) {  
            var ppg = plus.webview.currentWebview();  
            //var ppg = plus.webview.getWebviewById('a.html');  
            document.getElementById("ggg").innerText = "fire事件参数:" + e.detail.idd;  
            document.getElementById("ggg1").innerText = "页面预加载参数:" + ppg.idd;  
        })  

        document.getElementById("anniu").addEventListener('tap',function(){  
            //var indexPage=plus.webview.getWebviewById('index.html');  
            var indexPage=plus.webview.getLaunchWebview();//获取首页对象  
            console.log(indexPage);  
            mui.fire(indexPage,'backIndexPage',{str:"我回来了!"});  
            mui.back();  
        })  
    </script>  

</html>  
收起阅读 »

JS阻止冒泡方法

JS事件流其中一种是冒泡事件,当一个元素被触发一个事件时,该目标元素的事件会优先被执行,然后向外传播到每个祖先元素,恰如水里的一个泡泡似的,从产生就一直往上浮,到在水平面时,它才消失。在这个过程中,如果你只希望事件发生在目标元素,而不想它传播到祖先元素上去,那么你需要在“泡泡”离开对象之前刺破它。

  我在文档中写了一个层,<div id="need_hide">点击以外隐藏该层</div>,并为之设置了简单的样式,现在我希望点击该层以外的地方使之隐藏,那么我给根元素绑定了一个click事件,一点击html就隐藏该DIV,代码如下:
Javascript代码 收藏代码

document.documentElement.onclick = function() {    
    document.getElementById('need_hide').style.display = 'none';    
}    

  但是点击该层后,也使之隐藏了,这不是我希望得到的效果。由于该层属于根元素的子节点,所以它也被绑定了这个click事件,那么需在该元素被click时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码

function stopPropagation(e) {    
    e = e || window.event;    
    if(e.stopPropagation) { //W3C阻止冒泡方法    
        e.stopPropagation();    
    } else {    
        e.cancelBubble = true; //IE阻止冒泡方法    
    }    
}    
document.getElementById('need_hide').onclick = function(e) {    
    stopPropagation(e);    
}    

  如果还想增加一个链接:<a href="#" id="btn_show">显示层</a>,用它来控制该层显示出来,那么仍然需要在该链接被点击时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码

document.getElementById('btn_show').onclick = function(e) {    
    document.getElementById('need_hide').style.display = 'block';    
    stopPropagation(e);    
}  
继续阅读 »

JS事件流其中一种是冒泡事件,当一个元素被触发一个事件时,该目标元素的事件会优先被执行,然后向外传播到每个祖先元素,恰如水里的一个泡泡似的,从产生就一直往上浮,到在水平面时,它才消失。在这个过程中,如果你只希望事件发生在目标元素,而不想它传播到祖先元素上去,那么你需要在“泡泡”离开对象之前刺破它。

  我在文档中写了一个层,<div id="need_hide">点击以外隐藏该层</div>,并为之设置了简单的样式,现在我希望点击该层以外的地方使之隐藏,那么我给根元素绑定了一个click事件,一点击html就隐藏该DIV,代码如下:
Javascript代码 收藏代码

document.documentElement.onclick = function() {    
    document.getElementById('need_hide').style.display = 'none';    
}    

  但是点击该层后,也使之隐藏了,这不是我希望得到的效果。由于该层属于根元素的子节点,所以它也被绑定了这个click事件,那么需在该元素被click时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码

function stopPropagation(e) {    
    e = e || window.event;    
    if(e.stopPropagation) { //W3C阻止冒泡方法    
        e.stopPropagation();    
    } else {    
        e.cancelBubble = true; //IE阻止冒泡方法    
    }    
}    
document.getElementById('need_hide').onclick = function(e) {    
    stopPropagation(e);    
}    

  如果还想增加一个链接:<a href="#" id="btn_show">显示层</a>,用它来控制该层显示出来,那么仍然需要在该链接被点击时阻止冒泡事件的发生,加上以下代码:
Javascript代码 收藏代码

document.getElementById('btn_show').onclick = function(e) {    
    document.getElementById('need_hide').style.display = 'block';    
    stopPropagation(e);    
}  
收起阅读 »

移动页面点击穿透问题解决方案

近期在做页面的时候,遇到了点击遮罩层时穿透下层的checkbox的问题,由于为了兼顾用户的流畅度,只能使用tap事件,click事件虽然解决了穿透的问题,但总会有300ms的延时,因此最终使用settimeout方法规避了这个问题。下面是我找到的一篇造成这些问题的简单分析,希望对大家有用!
一.click与300ms延迟

移动浏览器提供一个特殊的功能:双击(double tap)放大

300ms的延迟就来自这里,用户碰触页面之后,需要等待一段时间来判断是不是双击(double tap)动作,而不是立即响应单击(click),等待的这段时间大约是300ms。之前有过简单介绍: 黯羽轻扬:HTML5触摸事件

移动事件提供了 touchstart 、 touchmove 、 touchend 却没有提供tap支持,主流框架(库)都是手动实现了自定义tap事件,以求消除300ms延迟,提高页面响应速度。对于简单的页面,可以把 touchstart 或者 touchend 当作tap来用,但存在一些问题,比如手指接触目标元素,按住不放,慢慢移出响应区域,会触发 touchstart 事件执行对应的事件处理器(本不应该触发), touchend 事件也存在类似的问题。

此外, 使用原生touch事件也存在点击穿透的问题 ,因为click是在touch系列事件发生后大约300ms才触发的,混用touch和click肯定会导致点透问题,下面详细介绍

二.点击穿透问题

点击穿透现象有3种:

点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件

蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件,touch事件触发之后,蒙层消失了,300ms后这个点的click事件fire,event的target自然就是按钮下面的元素,因为按钮跟蒙层一起消失了

跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转

因为 a标签跳转默认是click事件触发 ,所以原理和上面的完全相同

另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了

和蒙层的道理一样,js控制页面跳转的逻辑如果是绑定在touch事件上的,而且新页面中对应位置的元素绑定的是click事件,而且页面在300ms内完成了跳转,三个条件同时满足,就出现这种情况了

非要细分的话还有第四种,不过概率很低,就是新页面中对应位置元素恰好是a标签,然后就发生连续跳转了。。。诸如此类的,都是点击穿透问题

三.解决方案

问题已经很明了了,有很多解决方案,但思路不外乎2种:

不要混用touch和click

既然touch之后300ms会触发click,只用touch或者只用click就自然不会存在问题了

吃掉(或者说是消费掉)touch之后的click

依旧用tap,只是在可能发生点击穿透的情形做额外的处理,拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测(配合全局flag)等等,能吃掉就行

详细解决方案:

只用touch

最简单的解决方案,完美解决点击穿透问题

把页面内所有click全部换成touch事件( touchstart 、’touchend’、’tap’), 需要特别注意 a标签,a标签的href也是click,需要去掉换成js控制的跳转,或者直接改成span + tap控制跳转。如果要求不高,不在乎滑走或者滑进来触发事件的话,span + touchend就可以了,毕竟tap需要引入第三方库

不用a标签其实没什么,移动app开发不用考虑SEO,即便用了a标签,一般也会去掉所有默认样式,不如直接用span

只用click

下下策 ,因为会带来300ms延迟,页面内任何一个自定义交互都将增加300毫秒延迟,想想都慢

不用touch就不会存在touch之后300ms触发click的问题,如果交互性要求不高可以这么做, 强烈不推荐 ,快一点总是好的

拿个东西来挡住

比较笨的方法, 千万不要用

叶小钗的“菊花”大法,更多信息请查看 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

tap后延迟350ms再隐藏mask

改动最小,缺点是隐藏mask变慢了,350ms还是能感觉到慢的

只需要针对mask做处理就行,改动非常小,如果要求不高的话,用这个比较省力

pointer-events

比较麻烦且有缺陷, 不建议使用

mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应

缺陷是mask消失后的的350ms内,用户可以看到按钮下面的元素点着没反应,如果用户手速很快的话一定会发现

在下面元素的事件处理器里做检测(配合全局flag)

比较麻烦, 不建议使用

全局flag记录按钮点击的位置(坐标点),在下面元素的事件处理器里判断event的坐标点,如果相同则是那个可恶的click,拒绝响应

上面说的只是想法,没测试过,实在不行就用记录时间戳判断,等待350ms,这样就和 pointer-events 差不多

fastclick

好用的解决方案,不介意多加载几KB的话, 不建议使用 ,因为有人遇到了bug,更多信息请查看: Fastclick 导致click事件触发两次的问题

首先引入fastclick库,再把页面内所有touch事件都换成click,其实稍微有点麻烦,建议引入这几KB就为了解决点透问题不值得,不如用第一种方法呢
原文地址:http://www.tuicool.com/articles/6NfaUnM

继续阅读 »

近期在做页面的时候,遇到了点击遮罩层时穿透下层的checkbox的问题,由于为了兼顾用户的流畅度,只能使用tap事件,click事件虽然解决了穿透的问题,但总会有300ms的延时,因此最终使用settimeout方法规避了这个问题。下面是我找到的一篇造成这些问题的简单分析,希望对大家有用!
一.click与300ms延迟

移动浏览器提供一个特殊的功能:双击(double tap)放大

300ms的延迟就来自这里,用户碰触页面之后,需要等待一段时间来判断是不是双击(double tap)动作,而不是立即响应单击(click),等待的这段时间大约是300ms。之前有过简单介绍: 黯羽轻扬:HTML5触摸事件

移动事件提供了 touchstart 、 touchmove 、 touchend 却没有提供tap支持,主流框架(库)都是手动实现了自定义tap事件,以求消除300ms延迟,提高页面响应速度。对于简单的页面,可以把 touchstart 或者 touchend 当作tap来用,但存在一些问题,比如手指接触目标元素,按住不放,慢慢移出响应区域,会触发 touchstart 事件执行对应的事件处理器(本不应该触发), touchend 事件也存在类似的问题。

此外, 使用原生touch事件也存在点击穿透的问题 ,因为click是在touch系列事件发生后大约300ms才触发的,混用touch和click肯定会导致点透问题,下面详细介绍

二.点击穿透问题

点击穿透现象有3种:

点击穿透问题:点击蒙层(mask)上的关闭按钮,蒙层消失后发现触发了按钮下面元素的click事件

蒙层的关闭按钮绑定的是touch事件,而按钮下面元素绑定的是click事件,touch事件触发之后,蒙层消失了,300ms后这个点的click事件fire,event的target自然就是按钮下面的元素,因为按钮跟蒙层一起消失了

跨页面点击穿透问题:如果按钮下面恰好是一个有href属性的a标签,那么页面就会发生跳转

因为 a标签跳转默认是click事件触发 ,所以原理和上面的完全相同

另一种跨页面点击穿透问题:这次没有mask了,直接点击页内按钮跳转至新页,然后发现新页面中对应位置元素的click事件被触发了

和蒙层的道理一样,js控制页面跳转的逻辑如果是绑定在touch事件上的,而且新页面中对应位置的元素绑定的是click事件,而且页面在300ms内完成了跳转,三个条件同时满足,就出现这种情况了

非要细分的话还有第四种,不过概率很低,就是新页面中对应位置元素恰好是a标签,然后就发生连续跳转了。。。诸如此类的,都是点击穿透问题

三.解决方案

问题已经很明了了,有很多解决方案,但思路不外乎2种:

不要混用touch和click

既然touch之后300ms会触发click,只用touch或者只用click就自然不会存在问题了

吃掉(或者说是消费掉)touch之后的click

依旧用tap,只是在可能发生点击穿透的情形做额外的处理,拿个东西来挡住、或者tap后延迟350毫秒再隐藏mask、pointer-events、在下面元素的事件处理器里做检测(配合全局flag)等等,能吃掉就行

详细解决方案:

只用touch

最简单的解决方案,完美解决点击穿透问题

把页面内所有click全部换成touch事件( touchstart 、’touchend’、’tap’), 需要特别注意 a标签,a标签的href也是click,需要去掉换成js控制的跳转,或者直接改成span + tap控制跳转。如果要求不高,不在乎滑走或者滑进来触发事件的话,span + touchend就可以了,毕竟tap需要引入第三方库

不用a标签其实没什么,移动app开发不用考虑SEO,即便用了a标签,一般也会去掉所有默认样式,不如直接用span

只用click

下下策 ,因为会带来300ms延迟,页面内任何一个自定义交互都将增加300毫秒延迟,想想都慢

不用touch就不会存在touch之后300ms触发click的问题,如果交互性要求不高可以这么做, 强烈不推荐 ,快一点总是好的

拿个东西来挡住

比较笨的方法, 千万不要用

叶小钗的“菊花”大法,更多信息请查看 【移动端兼容问题研究】javascript事件机制详解(涉及移动兼容)

tap后延迟350ms再隐藏mask

改动最小,缺点是隐藏mask变慢了,350ms还是能感觉到慢的

只需要针对mask做处理就行,改动非常小,如果要求不高的话,用这个比较省力

pointer-events

比较麻烦且有缺陷, 不建议使用

mask隐藏后,给按钮下面元素添上 pointer-events: none; 样式,让click穿过去,350ms后去掉这个样式,恢复响应

缺陷是mask消失后的的350ms内,用户可以看到按钮下面的元素点着没反应,如果用户手速很快的话一定会发现

在下面元素的事件处理器里做检测(配合全局flag)

比较麻烦, 不建议使用

全局flag记录按钮点击的位置(坐标点),在下面元素的事件处理器里判断event的坐标点,如果相同则是那个可恶的click,拒绝响应

上面说的只是想法,没测试过,实在不行就用记录时间戳判断,等待350ms,这样就和 pointer-events 差不多

fastclick

好用的解决方案,不介意多加载几KB的话, 不建议使用 ,因为有人遇到了bug,更多信息请查看: Fastclick 导致click事件触发两次的问题

首先引入fastclick库,再把页面内所有touch事件都换成click,其实稍微有点麻烦,建议引入这几KB就为了解决点透问题不值得,不如用第一种方法呢
原文地址:http://www.tuicool.com/articles/6NfaUnM

收起阅读 »