设置微信自定义分享内容

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
/**
* 设置微信自定义分享内容
*/
var config = {
title: document.title,
only_title: '',
desc: '',
imgUrl: 'share_wechat.jpg'
};
define(function () {
return function weixin(config) {
if(/micromessenger/i.test(navigator.userAgent)) {
if(typeof requirejs == 'function') {
requirejs(['//xxx/wechat/sdk/share.js'], function (weixinShare) {
if(weixinShare && typeof weixinShare == 'function') {
weixinShare({
shareData: config
});
}
});
} else {
var script = document.createElement('script');
script.src = '//xxx/wechat/sdk/share.js';
script.onload = function goShare() {
if(window.weixinShare && typeof window.weixinShare == 'function') {
window.weixinShare({
shareData: config
});
}
};
document.body.appendChild(script);
}
}
};
});

小程序开发

官方文档

https://mp.weixin.qq.com/debug/wxadoc/dev/index.html?t=20161107

设计规范

https://mp.weixin.qq.com/debug/wxadoc/design/index.html?t=20161107

工具

IDE
https://mp.weixin.qq.com/debug/wxadoc/dev/devtools/download.html?t=20161107

教程

从搭建一个微信小程序开始
https://www.qcloud.com/act/event/yingyonghao.html?from=timeline&isappinstalled=0

开发框架WePY

https://tencent.github.io/wepy/document.html#/

资源汇总

https://github.com/justjavac/awesome-wechat-weapp


滚动 scroll 性能优化

在绑定 scroll 这类事件时,当它发生时,它被触发的频次非常高,间隔很近。如果事件中涉及到大量的位置计算、DOM 操作、元素重绘等工作且这些工作无法在下一个 scroll 事件触发前完成,就会造成浏览器掉帧。加之用户鼠标滚动往往是连续的,就会持续触发 scroll 事件导致掉帧扩大、浏览器 CPU 使用率增加、用户体验受到影响。

优化方法

1、防抖(debounce)

防抖技术可以把多个顺序地调用合并成一次,即在规定的时间间隔内只执行一次。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 简单的防抖动函数
function debounce(func, wait, immediate) {
// 定时器变量
var timeout;
return function() {
// 每次触发 scroll handler 时先清除定时器
clearTimeout(timeout);
// 指定 xx ms 后触发真正想进行的操作 handler
timeout = setTimeout(func, wait);
};
};
// 实际想绑定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}
// 采用了防抖动
window.addEventListener('scroll',debounce(realFunc,500));
// 没采用防抖动
window.addEventListener('scroll',realFunc);

2、节流(throttle)

节流技术只允许一个函数在 x 毫秒内执行一次,跟防抖技术主要的不同在于,保证 x 毫秒内至少执行一次。

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
// 简单的节流函数function throttle(func, wait, mustRun) {
var timeout,
startTime = new Date();
return function() {
var context = this,
args = arguments,
curTime = new Date();
clearTimeout(timeout);
// 如果达到了规定的触发时间间隔,触发 handler
if(curTime - startTime >= mustRun){
func.apply(context,args);
startTime = curTime;
// 没达到触发间隔,重新设定定时器
}else{
timeout = setTimeout(func, wait);
}
};
};
// 实际想绑定在 scroll 事件上的 handler
function realFunc(){
console.log("Success");
}
// 采用了节流函数
window.addEventListener('scroll',throttle(realFunc,500,1000));

3、requestAnimationFrame实现节流方法

requestAnimationFrame 可替代 throttle,函数需要重新计算和渲染屏幕上的元素时,想保证动画或变化的平滑性,可以用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var ticking = false; // rAF 触发锁
function onScroll(){
if(!ticking) {
requestAnimationFrame(realFunc);
ticking = true;
}
}
function realFunc(){
// do something...
console.log("Success");
ticking = false;
}
// 滚动事件监听
window.addEventListener('scroll', onScroll, false);

详见:
高性能滚动 scroll 及页面渲染优化
实例解析防抖和节流函数
页面高性能滚动scroll优化——防抖与节流

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
function debounce(fn, wait) {
var timmer
return function() {
// 第一次触发函数的时候,延迟delay时间执行,如果在delay时间段内再次触发该函数,则重新开始计时
// 如果delay时间段内没有触发该函数,则执行该函数
if (timmer) {
clearTimeout(timmer)
}
timmer = setTimeout(fn, wait)
}
}
function throttle(fn, delay) {
let timer = null;
return function() {
if(timer) return false
timer = setTimeout(() => {
fn()
timer = null
}, delay)
}
}
function throttle(func, wait) {
var args,
result,
thisArg,
timeoutId,
lastCalled = 0;
return function() {
var now = new Date,
remain = wait - (now - lastCalled);
args = arguments;
thisArg = this;
if (remain <= 0) {
lastCalled = now;
result = func.apply(thisArg, args);
}
else if (!timeoutId) {
timeoutId = setTimeout(() => {
lastCalled = new Date;
timeoutId = null;
result = func.apply(thisArg, args);
}, remain);
}
return result;
};
}

ES6 解构

数组

从数组中取元素

1
2
3
4
5
6
7
const names = ['Luke', 'Eva', 'Phil'];
const [first] = names;
console.log(first); // 'Luke'
const [first, second] = names;
console.log(first, second); // 'Luke' 'Eva'

元素缺失时的默认值

1
2
const [first, second, third, fourth='Martin'] = names;
console.log(fourth); // 'Martin'

跳过数组中的元素

1
2
var [first, , second] = names;
console.log(first, second); // 'Luke' 'Phil'

分配数组中剩下的给某元素

1
2
var [first, ...rest] = names;
console.log(rest); // ['Eva','Phil']

对象

1
2
3
4
5
6
7
8
const person = {
name: 'Luke',
age: '24',
facts: {
hobby: 'Photo',
work: 'Software Developer'
}
}

从对象中提取数据

1
2
const {name, age} = person;
console.log(name, age); // 'Luke' '24'

提取嵌套值

1
2
const {facts: {hobby}} = person;
console.log(hobby); // 'Photo'

数据缺失时的默认值

1
2
const {hometown = 'Unknown'} = person;
console.log(hometown); // 'Unknown'

解构函数参数

1
2
3
4
5
const toString = ({name, age}) => {
return `${name} is ${age} years old`;
}
toString(person); // Luke is 24 years old

min-height的百分比

设置min-height的元素即使内容的高度很少时也能撑开到min-height设置的高度;当内容的高度大于min-height时就设置为内容的高度.

要使min-height的百分比值生效,其父元素的height值必须为一个固定的高度或者是一个有效的百分比高度.

值得注意的是,父元素设置了有效的min-height但没有设置height属性时,子元素的height和min-height的百分比不会生效.因为设置height和min-height必须基于一个设置了固定高度或者是一个有效百分比高度的父元素.


判断窗口滚动到底部

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
onScroll: function() {
var self = this;
var BOTTOM_OFFSET = 0;
$(window).scroll(function () {
var $currentWindow = $(window);
//当前窗口的高度
var windowHeight = $currentWindow.height();
//当前滚动条从上往下滚动的距离
var scrollTop = $currentWindow.scrollTop();
//当前文档的高度
var docHeight = $(document).height();
//当 滚动条距底部的距离 + 滚动条滚动的距离 >= 文档的高度 - 窗口的高度
if ((BOTTOM_OFFSET + scrollTop) >= docHeight - windowHeight) {
self.loadMore();
}
});
}

vue实例方法 / 事件

vm.$on( event, callback )

参数:

{String} event
{Function} callback
用法:

监听当前实例上的自定义事件。事件可以由 vm.$emit, vm.$dispatch 或 vm.$broadcast触发。传入这些方法的附加参数都会传入这个方法的回调。

示例:

vm.$on(‘test’, function (msg) {
console.log(msg)
})
vm.$emit(‘test’, ‘hi’)
// -> “hi”

vm.$emit( event, […args] )

参数:

{String} event
[…args]
触发当前实例上的事件。附加参数都会传给监听器回调。

vm.$dispatch( event, […args] )

参数:

{String} event
[…args]
用法:

派发事件,首先在实例上触发它,然后沿着父链向上冒泡在触发一个监听器后停止,除非它返回 true。附加参数都会传给监听器回调。

vm.$broadcast( event, […args] )

参数:

{String} event
[…args]
用法:

广播事件,通知给当前实例的全部后代。因为后代有多个枝杈,事件将沿着各“路径”通知。每条路径上的通知在触发一个监听器后停止,除非它返回 true。


元素滚动时禁止父元素滚动

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
import Vue from 'vue'
// from: http://www.zhangxinxu.com/wordpress/2015/12/element-scroll-prevent-parent-element-scroll-js/
function handleStopScroll (e) {
let el = e.currentTarget
let scrollTop = el.scrollTop
let scrollHeight = el.scrollHeight
let height = el.clientHeight
let delta = (e.wheelDelta) ? e.wheelDelta : -(e.detail || 0)
console.log(scrollTop, scrollHeight, height, delta)
// delta > 0 上滚
// delta < 0 下滚
if ((delta > 0 && scrollTop <= delta) ||
(delta < 0 && scrollHeight - height - scrollTop <= -1 * delta)) {
el.scrollTop = delta > 0 ? 0 : scrollHeight
event.preventDefault()
}
}
let eventType = 'mousewheel'
if (window.document.mozHidden !== undefined) {
eventType = 'DOMMouseScroll'
}
Vue.directive('stop-scroll', {
bind () {
this.el.addEventListener(eventType, handleStopScroll, false)
},
unbind () {
this.el.removeEventListener(eventType, handleStopScroll)
}
})

css 垂直居中

绝对定位

1
2
3
4
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);

flex

1
2
3
4
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;

原型与继承

函数对象

由function创造出来的函数
系统内置函数对象 Function,Object,Number,String
只有函数对象才有 prototype 属性

原型对象 prototype

指针 proto

所有对象都有proto属性,指向构造该对象的构造函数的prototype
function Person() {
this.name = ‘name’
}
var person1 = new Person()
person1._proto = Person.prototype

构造函数 constructor

function Person() {
this.name = ‘name’
}
var person1 = new Person()
person1.constructor = Person
person1._proto.constructor = Person.prototype.constructor = Person

简单原型链继承

1
2
3
4
5
6
7
8
function Super() {
this.name = 'super'
}
function Sub() {
}
// 利用原型链实现继承, 缺点:包含引用类型值的原型属性会被所有实例共享
Sub.prototype = new Super()

构造函数继承

1
2
3
4
5
6
7
function Super() {
this.name = 'super'
}
// 缺点:方法都只能在构造函数中定义,没有办法实现方法的复用
function Sub() {
Super.call(this, ...arguments)
}

组合式继承

使用原型链实现对原型方法的继承,使用构造函数实现对实例属性的继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Super() {
this.name = 'super'
}
Super.prototype.sayName = function() {
return this.name
}
function Sub() {
// 通过 构造函数继承属性
Super.call(this, ...arguments)
}
// 利用原型链实现继承, 缺点:包含引用类型值的原型属性会被所有实例共享
Sub.prototype = new Super()
// 重写了 Sub 的 prototype 属性,因此其 constructor 也被重写了,需要手动修正
Sub.prototype.constructor = Sub
// 定义子类自己的方法
Sub.prototype.sayAge = function() {
return this.age
}

原型式继承

寄生式继承

1
2
3
4
5
6
7
function createAnother(original) {
var clone = Object.create(original)
clone.sayHi = function() {
console.log("Hi")
}
return clone
}

组合寄生式继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Super() {
this.name = 'super'
}
Super.prototype.sayName = function() {
return this.name
}
function Sub() {
Super.call(this, ...arguments)
}
Sub.prototype = Object.create(Super.prototype)
Sub.prototype.constructor = Sub
Sub.prototype.sayAge = function() {
return this.age
}