Skip to content

Commit 38c396e

Browse files
committed
feat: 小程序定时器库初始化
1 parent e601bb9 commit 38c396e

File tree

7 files changed

+3388
-0
lines changed

7 files changed

+3388
-0
lines changed

.eslintrc.js

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* 该 ESLint 配置扩展自 eslint-config-o2team-wx
3+
* https://www.npmjs.com/package/eslint-config-o2team-wx
4+
* o2team-wx 这一套规则是参考了 StandardJS 和 Airbnb 的 JS 规范,然后结合业务中的最佳实践整理输出的。
5+
*/
6+
module.exports = {
7+
'extends': 'o2team-wx',
8+
'plugins': [
9+
'html',
10+
'import'
11+
],
12+
'settings': {
13+
'html/html-extensions': ['.wxml']
14+
},
15+
'rules': {
16+
'newline-per-chained-call': 'off',
17+
'eqeqeq': 'off',
18+
'indent': ['error', 2, { SwitchCase: 1 }],
19+
'prefer-rest-params': 'off',
20+
'prefer-template': 'off',
21+
'no-else-return': 'off',
22+
'no-nested-ternary': 'off',
23+
'brace-style': 'off',
24+
'semi': 'off',
25+
'camelcase': ['off', { properties: 'never' }], // ESLint 配置问题,暂时不强制所有变量名都用驼峰式命名
26+
'array-callback-return': 'off', // 暂时关闭
27+
'prefer-const': 'warn',
28+
'no-mixed-operators': 'off',
29+
'callback-return': 'warn',
30+
'class-methods-use-this': 'warn',
31+
// 强制使用ES6 module,便于treeshaking
32+
'import/no-commonjs': 'error',
33+
'import/no-amd': 'error',
34+
'no-debugger': 0
35+
}
36+
}

README.md

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# timer-miniprogram
2+
3+
小程序定时器管理库,更合理地使用 setTimeout 和 setInterval
4+
5+
## 使用
6+
7+
可参考 example 目录下的示例项目或参照以下流程:
8+
9+
1. 通过 npm 安装
10+
11+
```shell
12+
npm install --save timer-miniprogram
13+
```
14+
15+
安装完成之后在微信开发者工具中点击构建 npm。
16+
17+
2. 导入小程序适配版本的 timer-miniprogram
18+
19+
```javascript
20+
import { TimerBehavior } from 'timer-miniprogram'
21+
// 在页面中使用
22+
Page({
23+
behaviors: [TimerBehavior],
24+
onReady() {
25+
this.$setTimeout(() => {
26+
console.log('setTimeout')
27+
})
28+
this.$setInterval(() => {
29+
console.log('setTimeout')
30+
})
31+
}
32+
})
33+
34+
// 在组件中使用
35+
Components({
36+
behaviors: [TimerBehavior],
37+
ready() {
38+
this.$setTimeout(() => {
39+
console.log('setTimeout')
40+
})
41+
this.$setInterval(() => {
42+
console.log('setTimeout')
43+
})
44+
}
45+
})
46+

package.json

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"name": "timer-miniprogram",
3+
"version": "0.0.1",
4+
"description": "小程序定时器管理库,更合理地使用 setTimeout 和 setInterval",
5+
"main": "src/index.js",
6+
"miniprogram": "src",
7+
"scripts": {
8+
"lint": "eslint \"src/*.js\""
9+
},
10+
"repository": {
11+
"type": "git",
12+
"url": "git+https://github.com/o2team/timer-miniprogram.git"
13+
},
14+
"keywords": [
15+
"setTimeout",
16+
"setInterval",
17+
"miniprogram",
18+
"微信小程序定时器"
19+
],
20+
"author": "jimczj",
21+
"license": "MIT",
22+
"lint-staged": {
23+
"*.js": [
24+
"eslint --quiet --cache --fix",
25+
"git add"
26+
]
27+
},
28+
"devDependencies": {
29+
"@commitlint/cli": "7.2.1",
30+
"@commitlint/format": "7.2.1",
31+
"@commitlint/lint": "7.2.1",
32+
"@commitlint/read": "^7.6.0",
33+
"eslint": "^4.19.1",
34+
"eslint-config-o2team-wx": "^1.0.1",
35+
"eslint-plugin-html": "^4.0.2",
36+
"eslint-plugin-import": "^2.18.2",
37+
"husky": "^0.14.3",
38+
"lint-staged": "^7.0.0",
39+
"prettier": "^1.12.1",
40+
"prettier-eslint": "^8.8.1"
41+
},
42+
"bugs": {
43+
"url": "https://github.com/o2team/timer-miniprogram/issues"
44+
},
45+
"homepage": "https://github.com/o2team/timer-miniprogram#readme"
46+
}

src/behavior.js

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import { Timer } from './timer'
2+
3+
const TimerBehavior = Behavior({
4+
pageLifetimes: {
5+
show () { Timer.pageShow(this.__wxWebviewId__) },
6+
hide () { Timer.pageHide(this.__wxWebviewId__) }
7+
},
8+
methods: {
9+
$setTimeout (fn = () => {}, timeout = 0, ...arg) {
10+
const timer = new Timer(false, this.__wxWebviewId__, fn, timeout, ...arg)
11+
return timer.id
12+
},
13+
$setInterval (fn = () => {}, timeout = 0, ...arg) {
14+
const timer = new Timer(true, this.__wxWebviewId__, fn, timeout, ...arg)
15+
return timer.id
16+
},
17+
$clearInterval (id) {
18+
Timer.clear(this.__wxWebviewId__, id)
19+
},
20+
$clearTimeout (id) {
21+
Timer.clear(this.__wxWebviewId__, id)
22+
},
23+
},
24+
created () { Timer.pageLoad(this.__wxWebviewId__) },
25+
detached () { Timer.pageUnLoad(this.__wxWebviewId__) },
26+
})
27+
28+
export { TimerBehavior }

src/index.js

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './timer'
2+
export * from './behavior'

src/timer.js

+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/**
2+
* 定时器管理库
3+
* @author chenzeji
4+
*/
5+
6+
class Timer {
7+
/**
8+
* 清除定时器
9+
* @param {String} pageId 页面 id
10+
* @param {String} id 定时器 id
11+
*/
12+
static clear (pageId, id) {
13+
const { timerStore } = Timer.pageStore.get(pageId) || {}
14+
if (!timerStore) return
15+
16+
const timer = timerStore.get(id)
17+
if (!timer) return
18+
19+
clearTimeout(timer.timerId)
20+
timer.timerId = ''
21+
timerStore.delete(id)
22+
}
23+
24+
/**
25+
* 页面加载处理函数
26+
* @param {String} pageId 页面 id
27+
*/
28+
static pageLoad (pageId) {
29+
Timer.pageStore.set(pageId, {
30+
isActive: true,
31+
timerStore: new Map()
32+
})
33+
}
34+
35+
/**
36+
* 页面展示处理函数
37+
* @param {String} pageId 页面 id
38+
*/
39+
static pageShow (pageId) {
40+
const page = Timer.pageStore.get(pageId) || {}
41+
42+
/* 没有隐藏,不需要恢复定时器 */
43+
if (page.isActive) return
44+
45+
page.isActive = true
46+
page.timerStore && page.timerStore.forEach(timer => timer.start())
47+
}
48+
49+
/**
50+
* 页面隐藏处理函数
51+
* @param {String} pageId 页面 id
52+
*/
53+
static pageHide (pageId) {
54+
const page = Timer.pageStore.get(pageId) || {}
55+
page.timerStore && page.timerStore.forEach(timer => timer.suspend())
56+
page.isActive = false
57+
}
58+
59+
/**
60+
* 页面卸载处理函数
61+
* @param {String} pageId 页面 id
62+
*/
63+
static pageUnLoad (pageId) {
64+
Timer.pageHide(pageId)
65+
Timer.pageStore.delete(pageId)
66+
}
67+
68+
/**
69+
* 构造函数
70+
* @param {Boolean} isInterval 是否是 setInterval
71+
* @param {String} pageId 页面 id
72+
* @param {Function} fn 回调函数
73+
* @param {Number} timeout 定时器执行时间间隔
74+
* @param {...any} arg 定时器其他参数
75+
*/
76+
constructor (isInterval = false, pageId = '', fn = () => {}, timeout = 0, ...arg) {
77+
this.id = ++Timer.count // 定时器递增 id
78+
this.fn = fn
79+
this.timeout = timeout
80+
this.restTime = timeout // 定时器剩余计时时间
81+
this.pageId = pageId
82+
this.isInterval = isInterval
83+
this.arg = arg
84+
85+
/* 存储定时器 */
86+
const { timerStore } = Timer.pageStore.get(pageId) || {}
87+
timerStore && timerStore.set(this.id, this)
88+
89+
this.start()
90+
}
91+
92+
/**
93+
* 启动定时器
94+
*/
95+
start () {
96+
const { isActive, timerStore } = Timer.pageStore.get(this.pageId) || {}
97+
/* 页面隐藏,不创建定时器 */
98+
if (this.restTime < 0 || !isActive) return
99+
100+
this.startTime = +new Date()
101+
102+
if (this.isInterval) {
103+
/* setInterval */
104+
const cb = (...arg) => {
105+
this.fn(...arg)
106+
/* timerId 为空表示被 clearInterval */
107+
if (this.timerId) this.timerId = setTimeout(cb, this.timeout, ...this.arg)
108+
}
109+
this.timerId = setTimeout(cb, this.restTime, ...this.arg)
110+
return
111+
}
112+
/* setTimeout */
113+
const cb = (...arg) => {
114+
this.fn(...arg)
115+
timerStore && timerStore.delete(this.id)
116+
}
117+
this.timerId = setTimeout(cb, this.restTime, ...this.arg)
118+
}
119+
120+
/* 暂停定时器 */
121+
suspend () {
122+
if (this.timeout > 0) {
123+
const now = +new Date()
124+
const nextRestTime = this.restTime - (now - this.startTime)
125+
this.restTime = this.isInterval ? Math.abs(nextRestTime) % this.timeout : nextRestTime
126+
}
127+
clearTimeout(this.timerId)
128+
}
129+
}
130+
131+
/* 定时器增量 id */
132+
Timer.count = 0
133+
/* 存储页面定时器和页面显示或隐藏状态 */
134+
Timer.pageStore = new Map()
135+
136+
export { Timer }

0 commit comments

Comments
 (0)