1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
"use strict";
console.log("main1");
// 该函数仅在 Node.js 环境下可以使用
process.nextTick(function () {
console.log("process.nextTick1");
});
setTimeout(function () {
console.log("setTimeout");
process.nextTick(function () {
console.log("process.nextTick2");
});
}, 0);
new Promise(function (resolve, reject) {
console.log("promise");
resolve();
}).then(function () {
console.log("promise then");
});
console.log("main");
  • Node.js 提供的 nextTick 和 setImmediate
  • nexTick 和 setImmediate 属于 node 中 process 模块中方法
  • process.nextTick()属于 idle 观察者,setImmediate()属 check 观察者。
  • 在每一轮循环检查中,idle 观察者先于 I/O 观察者,I/O 观察者先 check 观察者。
  • idle 观察者,也就是事件轮询最先进行的任务 I/O 观察者,也就是事件轮询的任务(任务中的回调函数)
  • check 观察者 事件轮询中的任务的结束
  • 在具体实现上,process.nextTick()的回调函数保存在一个数中,setImmediate() 的结果则是保存在链表。在行为上 process.nextTick() 在每轮循环中会将数组中的回调函数全部行完。而 setImmediate() 在每轮循环中执行链表中的一个回调函数。

1
2
3
4
5
6
7
8
9
// 获取容器高度,使页面滚动到容器底部
pageScrollToBottom: function() {
wx.createSelectorQuery().select('#j_page').boundingClientRect(function(rect){
// 使页面滚动到底部
wx.pageScrollTo({
scrollTop: rect.bottom
})
}).exec()
}
1
2
3
4
5
6
7
8
9
10
11
<view class="wc-mes">
<scroll-view
style="height: {{height}}px"
scroll-x="false"
scroll-y="true"
scroll-top="{{scrollTop}}"
>
<view class="scroll-content">...</view>
</scroll-view>
</view>
<view class="wc-bar">...</view>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 计算滚动区域的高度
calHeight() {
let that = this;
wx.createSelectorQuery().select('.wc-bar').boundingClientRect(function (rect) {
that.setData({
height: wx.getSystemInfoSync().windowHeight - rect.height
})
}).exec();
}

// 计算滚动的距离
calScrollTop() {
let that = this;
wx.createSelectorQuery().select('.scroll-content').boundingClientRect(function (rect) {
console.log(rect.height, that.data.height)
if (rect.height > that.data.height) {
that.setData({
scrollTop: rect.height
})
} else {
that.setData({
scrollTop: 0
})
}
}).exec();
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
import Vue from "vue";
import Router from "vue-router";
Vue.use(Router);

/**
* 简化router文件
* @param {[String]} path 定义路由路径
* @param {[String]} name 挂在文件路径
* @param {[String]} title 页面title
* @param {Object} [other={}] 路由其他参数
* @param {Array} [children=[]] 嵌套路由配置
* @return {Object} 返回router可用obj
*/
function path(path, name, title, other = {}, children = []) {
return Object.assign(
{
path: path,
name: name,
meta: {
title: title
},
component: resolve => require(["../pages/" + name + ".vue"], resolve),
children: children
},
other
);
}

let page = [];
// 测试页
page.push(
path("form", "test/form", "测试"),
path("table", "test/table", "acc")
);
// 流程管理
page.push(path("form", "process/list", ""));

export default new Router({
mode: "history",
routes: [
path("/", "index", "首页", { redirect: "/home/index" }),
path("/login", "public/login", "登录"),
//嵌套结构页
path("/home", "home", "", "", [
path("index", "public/home_index", ""), // 上下结构
path("aside", "public/aside", "", "", page) // 上左右结构
])
]
});

首先把安装 amfe-flexible,这里使用 npm install

1
npm i -S amfe-flexible

在入口文件 main.js 中引入

1
import "amfe-flexible/index.js";

在根目录的 index.html 的头部加入手机端适配的 meta 代码

阅读全文 »

1
2
3
4
.forbid-events {
pointer-events: none; //禁止元素成为鼠标事件的 target
pointer-events: auto; //与 pointer-events 属性未指定时的表现效果相同
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/* Keyword values */
pointer-events: auto;
pointer-events: none;
pointer-events: visiblePainted; /* SVG only */
pointer-events: visibleFill; /* SVG only */
pointer-events: visibleStroke; /* SVG only */
pointer-events: visible; /* SVG only */
pointer-events: painted; /* SVG only */
pointer-events: fill; /* SVG only */
pointer-events: stroke; /* SVG only */
pointer-events: all; /* SVG only */

/* Global values */
pointer-events: inherit;
pointer-events: initial;
pointer-events: unset;
  • auto——效果和没有定义 pointer-events 属性相同,鼠标不会穿透当前层。在 SVG 中,该值和 visiblePainted 的效果相同。

  • none——元素不再是鼠标事件的目标,鼠标不再监听当前层而去监听下面的层中的元素。但是如果它的子元素设置了 pointer-events 为其它值,比如 auto,鼠标还是会监听这个子元素的。

  • 使用 pointer-events 来阻止元素成为鼠标事件目标不一定意味着元素上的事件侦听器永不会触发

  • 如果元素后代明确指定了 pointer-events 属性并允许其成为鼠标事件的目标,那么指向该元素的任何事件在事件传播过程中都将通过父元素,并以适当的方式触发其上的事件侦听器

  • 当然位于屏幕上在父元素上但不在后代元素上的鼠标活动都不会被父元素和后代元素捕获(将会穿过父元素而指向位于其下面的元素)

强密码正则的要求是只能由数字,字母组成,不能有特殊符号, 并且长度限制在 8-10 位

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

1. 至少 8-16 个字符,至少 1 个大写字母,1 个小写字母和 1 个数字,其他可以是任意字符

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

或者:

阅读全文 »

判断字符串是否符合某种类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
function checkStr(str, type) {
switch (type) {
// 手机号码
case "phone":
return /^1[3|4|5|6|7|8|9][0-9]{9}$/.test(str);
// 座机
case "tel":
return /^(0\d{2,3}-\d{7,8})(-\d{1,4})?$/.test(str);
// 身份证
case "card":
return /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/.test(str);
// 密码以字母开头,长度在6~18之间,只能包含字母、数字和下划线
case "pwd":
return /^[a-zA-Z]\w{5,17}$/.test(str);
// 邮政编码
case "postal":
return /[1-9]\d{5}(?!\d)/.test(str);
// QQ号
case "QQ":
return /^[1-9][0-9]{4,9}$/.test(str);
// 邮箱
case "email":
return /^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$/.test(str);
// 金额(小数点2位)
case "money":
return /^\d*(?:\.\d{0,2})?$/.test(str);
// 网址
case "URL":
return /(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?/.test(str);
// IP
case "IP":
return /((?:(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d)\\.){3}(?:25[0-5]|2[0-4]\\d|[01]?\\d?\\d))/.test(str);
// 日期时间
case "date":
return /^(\d{4})\-(\d{2})\-(\d{2}) (\d{2})(?:\:\d{2}|:(\d{2}):(\d{2}))$/.test(str) || /^(\d{4})\-(\d{2})\-(\d{2})$/.test(str);
// 数字
case "number":
return /^[0-9]$/.test(str);
// 英文
case "english":
return /^[a-zA-Z]+$/.test(str);
// 中文
case "chinese":
return /^[\u4E00-\u9FA5]+$/.test(str);
// 小写
case "lower":
return /^[a-z]+$/.test(str);
// 大写
case "upper":
return /^[A-Z]+$/.test(str);
// HTML标记
case "HTML":
return /<("[^"]*"|'[^']*'|[^'">])*>/.test(str);
default:
return true;
}
}

是否电子邮箱格式

1
2
3
function email(value) {
return /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(value);
}

是否手机格式

阅读全文 »

javaScript 的变量类型

基本类型

基本数据类型有 numberstringbooleannullundefinedsymbol 以及未来 ES10 新增的 BigInt(任意精度整数)七类,变量是直接按值存放的,存放在栈内存中的简单数据段,可以直接访问。

引用类型

存放在堆内存中的对象,变量保存的是一个指针,这个指针指向另一个位置。当需要访问引用类型(如对象,数组等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

阅读全文 »

el-image 可通过 previewSrcList 开启预览大图的功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<div class="demo-image__preview">
<el-image
style="width: 100px; height: 100px"
:src="url"
:preview-src-list="srcList"
></el-image>
</div>

<script>
export default {
data() {
return {
url:
"https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg",
srcList: [
"https://fuss10.elemecdn.com/8/27/f01c15bb73e1ef3793e64e6b7bbccjpeg.jpeg",
"https://fuss10.elemecdn.com/1/8e/aeffeb4de74e2fde4bd74fc7b4486jpeg.jpeg"
]
};
}
};
</script>

关于微信公众号开发 config:invalid signature 错误的解决方法

  1. 确认签名算法正确,可用 http://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=jsapisign 页面工具进行校验。
  2. 确认 config 中 nonceStr(js 中驼峰标准大写 S), timestamp 与用以签名中的对应 noncestr, timestamp 一致。
  3. 确认 url 是页面完整的 url(请在当前页面 alert(location.href.split(‘#’)[0])确认),包括’http(s)://‘部分,以及’?’后面的 GET 参数部分,但不包括’#’hash 后面的部分。
  4. 确认 config 中的 appid 与用来获取 jsapi_ticket 的 appid 一致。
  5. 确保一定缓存 access_token 和 jsapi_ticket。
  6. html 的静态页面在前端通过 ajax 将 url 传到后台签名,前端需要用 js 获取当前页面除去’#’hash 部分的链接(可用 location.href.split(‘#’)[0]获取,而且需要 encodeURIComponent),因为页面一旦分享,微信客户端会在你的链接末尾加入其它参数,如果不是动态获取当前链接,将导致分享后的页面签名失败。

步骤:

  1. 首先你在页面 alert(location.href.split(‘#’)[0]);
  2. 然后你再打印出动态获取的 url 是否和你 alert 的地址是否一样。一定要一模一样,包括大小写。
    如果发现不一样,那就按照自己的需求改。反正要一样。验证签名一定可以通过的。