kangxueliang / my-blog Goto Github PK
View Code? Open in Web Editor NEW我自己的博客
我自己的博客
LazyMan("Hank")
输出
Hi! This is Hank!
LazyMan("Hank").sleep(10).eat("dinner")
输出
Hi! This is Hank!
等待10秒..
Wake up after 10
Eat dinner
LazyMan("Hank").eat("dinner").eat("supper")
输出
Hi This is Hank!
Eat dinner
Eat supper
LazyMan("Hank").sleepFirst(5).eat("supper")
等待5秒
Wake up after 5
Hi This is Hank!
Eat supper
function LazyMan(name) {
return new _LazyMan(name)
}
function _LazyMan(name) {
this.tasks = []
var fn = (n => () => {
console.log('hi ' + n )
this.next()
})(name)
this.tasks.push(fn)
setTimeout(() => {
this.next()
}, 0);
}
_LazyMan.prototype.next = function() {
let fn = this.tasks.shift()
fn && fn()
}
_LazyMan.prototype.eat = function(name) {
let fn = (n => () => {
console.log('eat ' + n)
this.next()
})(name)
this.tasks.push(fn)
return this
}
_LazyMan.prototype.sleep = function (delay) {
let fn = (d => () => {
setTimeout(() => {
console.log('Wake up after ' + d)
this.next()
}, d * 1000)
})(delay)
this.tasks.push(fn)
return this
}
_LazyMan.prototype.sleepFirst = function(delay) {
let fn = (d => () => {
setTimeout(() => {
console.log('等待 ' + d)
this.next()
}, d * 1000)
})(delay)
this.tasks.unshift(fn)
return this
}
啥也不多说了,有人已经写的很详细了。
详见: 轻松在 VPS 搭建 Shadowsocks 翻墙 ($2.5/月)
ps:我用的是搬瓦工的vps,便宜。(捂眼.jpg)
大家应该都知道,在Input里让文字垂直居中有很多种方案,最直接了当的一种:
input {
height: 20px;
line-height: 20px;
}
但移动端很明显的有一种bug就是,未输入文字时Input里的光标与input一样高,输入文字后,光标行为也变得很怪异,见图:
原因分析:
首先
IE:不管该行有没有文字,光标高度与font-size一致。
FF:该行有文字时,光标高度与font-size一致。该行无文字时,光标高度与input的height一致。
Chrome:该行无文字时,光标高度与line-height一致;该行有文字时,光标高度从input顶部到文字底部(这两种情况都是在有设定line-height的时候),如果没有line-height,则是与font-size一致。
解决方法:
1、给input设置一个较小的height,然后上下用padding填充起来
input{
height: 16px;
padding: 4px 0px;
font-size: 12px;
}
2、 外面包一层,然后给input设置一个较小的line-height
div {
height: 20px;
line-height: 20px;
}
div input {
height: 20px;
line-height: 10px
}
let pending = []; //声明一个数组用于存储每个ajax请求的取消函数和ajax标识
let cancelToken = axios.CancelToken;
let removePending = (config) => {
for(let p in pending){
if(pending[p].u === config.url + '&' + config.method) { //当当前请求在数组中存在时执行函数体
pending[p].f(); //执行取消操作
pending.splice(p, 1); //把这条记录从数组中移除
}
}
}
//添加请求拦截器
axios.interceptors.request.use(config=>{
removePending(config); //在一个ajax发送前执行一下取消操作
config.cancelToken = new cancelToken((c)=>{
// 这里的ajax标识我是用请求地址&请求方式拼接的字符串,当然你可以选择其他的一些方式
pending.push({ u: config.url + '&' + config.method, f: c });
});
return config;
},error => {
return Promise.reject(error);
});
//添加响应拦截器
axios.interceptors.response.use(response=>{
removePending(res.config); //在一个ajax响应后再执行一下取消操作,把已经完成的请求从pending中移除
return response;
},error =>{
return { data: { } }; 返回一个空对象,主要是防止控制台报错
});
最近完成了一个移动端活动页面里插入视频播放的需求,现在来说一下自己的经验与碰到的坑。
既然是插入视频,用的肯定是h5的video标签了,没啥异议,直接开干!对了,先来看一下效果图:
六小龄童领全民拜年
先来简单分析一下video标签。
MDN上的属性有以下几个:(只说主要的、常用的)
再来说两个方法:
所以一般来说,一个video标签长这样:(vue框架)
<video id="video"
src="/video1.mp4" // 资源路径
controls = "true" // 是否有控制条
poster="/begin.jpg9" // 视频封面
preload="auto" // 加载的形式
x-webkit-airplay="allow" // 使此视频支持ios的AirPlay功能
webkit-playsinline="true" // 视频播放时局域播放,不脱离文档流.需要APP支持,目前ios支持
playsinline="true"
x5-video-player-type="h5" // 启用H5播放器,是wechat安卓版特性
x5-video-player-fullscreen="true" // 安卓机全屏设置
@timeupdate="update()" // 检测播放时间回调
@ended="playEnd()"> // 播放结束回调
您的设备或浏览器暂不支持 video 标签。
</video>
对于iOS来说
<video id="video" src="xx.mp4" playsinline webkit-playsinline></video>
即可。
对于安卓来说,有两种办法
第一种
<div>
<video id="video"
src="video.mp4"
x5-video-player-type="h5"
x5-video-player-fullscreen="true"
x5-video-orientation="portraint"
style="object-fit:fill">
</video>
</div>
优点:全屏显示,无控制条
缺点:导航栏消失,某些机型退出播放时会有短暂黑屏。
第二种
<div ontouchmove="{return false}" onclick="{return false}">
<video id="video" playsinline="true">
</video>
</div>
然后设置视频video标签样式:
video {
margin: 0;
padding: 0;
width: 100%;
//height: 100%; ios设置该属性可以达到全屏显示,但稍有压缩,android会屏幕两边留有黑边。
object-fit: fill;
object-position: top;
z-index: 2;
position: relative;
user-select: none;
outline: none;
}
优点:有导航栏,退出播放无黑屏
缺点:其实是有控制条的,但是通过禁止用户触摸和点击,把控制条隐藏在界面外,导致界面缺失。
如果设置高度,可能导致android机型屏幕两边留有黑边,与视屏的尺寸有一定关系。而且不同的机型的表 现不同。
这个就不用说了,安卓始终不支持自动播放。ios本来也不行,必须引导用户点击,但微信提供了一个事件WeixinJSBridgeReady,在微信嵌入webview全局的这个事件触发后,视频仍可以自动播放。
document.addEventListener("WeixinJSBridgeReady", function (){
video.play();
}, false)
尽量只用timeupdate与ended两个事件,其他的诸如'loadstart','canplay','canplaythrough','ended','timeupdate'.....等等,会产生不一致的效果,不建议使用。
当前,video 元素支持三种视频格式:
Ogg = 带有 Theora 视频编码和 Vorbis 音频编码的 Ogg 文件
MPEG4 = 带有 H.264 视频编码和 AAC 音频编码的 MPEG 4 文件
WebM = 带有 VP8 视频编码和 Vorbis 音频编码的 WebM 文件
当然了,最好使用mp4的,移动端支持较好。
如果你想保险起见,可以写成这样:
<video autoplay>
<source src="video.mp4" type="video/mp4">
<source src="video.webm" type="video/webm">
<source src="video.ogv" type="video/ogg">
</video>
done.
下面附上文章最开始案例的code:
需求:全屏展示,保留title,不显示控制条,可嵌入APP
vue如下:
<div class="page-two" v-el:pagetwo v-if="showTwo" ontouchmove="{return false}" onclick="{return false}">
<div class="video-wrap">
<video id="video" src="//img.dsimg.cn/m_station/special_events/new_year_friend_circle/video1.mp4"
poster="//img.dsimg.cn/m_station/special_events/new_year_friend_circle/begin.jpg"
preload="auto"
x-webkit-airplay="allow"
webkit-playsinline="true"
playsinline="true"
@timeupdate="update()"
@ended="playEnd()"
v-el:video
class="translate">
您的设备或浏览器暂不支持 video 标签。
</video>
<!--<div class="ignore ignore2" @click="playEnd()" v-if="showIgnore && isiOS && !isQQ">跳过</div>-->
<div class="ignore" @click="playEnd()" v-if="showIgnore && isiOS && !isQQ"><img src="//img.dsimg.cn/m_station/special_events/new_year_friend_circle/jump.png"></div>
</div>
</div>
样式如下:
.page-two {
position: absolute;
z-index: 3;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: black;
.video-wrap {
position: relative;
width: 100%;
height: 100%;
video {
margin: 0;
padding: 0;
//height: 100%; // 暂时保留,ios设置该属性可以达到全屏显示,但稍有压缩,android会屏幕两边留有黑边。
object-fit: fill;
object-position: top;
z-index: 2;
position: relative;
user-select: none;
outline: none;
}
}
}
先来说一下,ECMAScript中,规定了如下:
六种 基本 数据类型:
String:表示字符串,例如:"Howdy"
Number: 表示数字,例如: 42 或者 3.14159
Boolean: 布尔值,true 和 false
null:一个表明 null 值的特殊关键字。 JavaScript 是大小写敏感的,因此 null 与 Null、NULL或其他变量完全不同
undefined: 变量未定义时的属性
Symbol ( 在 ECMAScript 6 中新添加的类型).。一种数据类型,它的实例是唯一且不可改变的
以及 Object 对象
这里Object除了单纯的常说的对象外,还包括:Array, Function, RegExp, Date等等。
这里判断数据类型的方法如下:
一、typeof
typeof操作符返回一个字符串,表示未经计算的操作数的类型。返回的值包括:number、boolean、symbol、string、object、undefined、function等
typeof('') // "string" 可行
typeof(1) // "number" 可行
typeof(NaN) // "number" 不可行
typeof(false) // "boolean" 可行
typeof(null) // "object" 不可行
typeof(undefined) // "undefined" 可行
typeof(Symbol()) // "symbol" 可行
typeof({a:1}) // "object" 可行
typeof([1,2,3]) // "object" 不可行
typeof(() => {console.log(1)}) // "function" 不可行
typeof(new Set()) // "object" 不可行
typeof(new Map()) // "object" 不可行
typeof(new Date()) // "object" 不可行
typeof(new RegExp()) // "object" 不可行
实践证明,
1、typeof适用于:string、number、boolean、function、undefined的判断,也就是除了null以外的其余基本类型。
2、NaN,返回number,对于需要判断是否NaN的时候不实用
3、null 返回object类型
3、function 引用类型里唯一返回正确的,其余都返回object
所以,typeof的适用范围就是判断除null以外的基本类型和function,number类型还要判断NaN的时候。
二.、isNaN,Array.isArray()
isNaN(NaN) // true
Array.isArray([1,2,3]) // true
isNaN是判读NaN的唯一的可靠方法
Array.isArray本质是检测对象的[[class]]值。[[Class]] 是对象的一个内部属性,里面包含了对象的类型信息,其格式为 [object Xxx] ,Xxx 就是对应的具体类型 。对于数组而言,[[Class]] 的值就是 [object Array] 。
三、Object.prototype.toString().call
toString是Object的原型上的一个方法,返回当前对象的[[class]]。为了每个对象都能通过 Object.prototype.toString() 来检测,需要以 Function.prototype.call() 或者 Function.prototype.apply() 的形式来调用
Object.prototype.toString.call('') // "[object String]"
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call(NaN) // "[object Number]"
Object.prototype.toString.call(false) // "[object Boolean]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(Symbol()) // "[object Symbol]"
Object.prototype.toString.call({a: 1}) // "[object Object]"
Object.prototype.toString.call([1,2,3]) // "[object Array]"
Object.prototype.toString.call(() => {console.log(1)}) // "[object Function]"
Object.prototype.toString.call(new Set()) // "[object Set]"
Object.prototype.toString.call(new Map()) // "[object Map]"
Object.prototype.toString.call(new Date()) // "[object Date]"
Object.prototype.toString.call(new RegExp()) // "[object RegExp]"
基本满足了所有要求,除了NaN
四、instanceof(弃用)
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
例如:a.proto === b.prototype 即可用说a是b的实例, a instanceof b返回true
这里需要注意的是: instanceof检测的是 原型链 .
例如:
[] instanceof Array // true
Array instanceof Object // true
[] instanceof Object // true
so,instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型
五、constructor(弃用)
所有对象都会从它的原型上继承一个 constructor 属性。
''.constructor === String // true
new Number(1).constructor === Number // true
...
需要注意的是:
1、null 和 undefined不是有效的对象,没有constructor存在
2、依赖一个对象的 constructor 属性并不安全, 因为constructor是可以改变的
今天突然遇到一个需求,是让我根据从后台拿到的数据,来给页面设置title.因为我现在做的是h5移动端开发,用的vue,所以拿到这个需求后,我陷入了深深的思考……
想了半天没用的,因为我开发用vue,所以一开始我想着created的时候用ajax获取数据,然后把数据传给vue实例,然后直接赋值给title标签内。
<title>{{title}}</title>
后来一想,这样还得进行父子组件的通信,有点啰嗦,要不用vuex?不行,没什么卵用。此路不通,又陷入了思考中……
要不,一开始不给页面设置title,然后等接受了数据之后,新建一个title元素,然后再插到head里面去?
var title = document.createElement("title")
title.innerText = data.title
document.head.appendChild(title)
或者直接
document.getElementsByTagName('title')[0].innerHTML = data.title
倒是可行,可是感觉有点low,有没有更好的办法呢?
然后,然后……
我突然灵光一闪,直接这样
document.title = data.title
可行,done……
But,世事总是无常的,根据微信iOS开发适配指南,
WTF?意思就是老版本的iOS微信浏览器修改页面标题无法正常显示呗……虽然2017年三月份过去半年了,但保不定还有一部分不升级微信,算了,还得做个兼容,来,开始吧……
首先,分析这个bug出现的原因,是因为微信之前使用的内核是UIWebView,并没有类似titleChange事件,虽然document.title已经修改了,但无法做出反应。
有没有什么hack方案?
谷歌了一番,还真有……代码如下:
function changeTitle(title) {
document.title = title
$('<iframe src="/title.html" style="display: none"></iframe>').one('load', function() {
setTimeout(() => {
$(this).remove()
}, 0)
})
}
// when route change use this update your page title
changeTitle(title)
优点就是适配通用,比较完美的实现了功能
缺点也很明显,多发送了一个请求……
等等,为什么加了一个iframe再拿掉就可以了呢?
原因:在native里打开网页,一般是通过webview搭配naviBar实现的。webview负责显示网页,naviBar负责显示标题、后退和关闭等信息。naviBar上显示的标题即是通过webview获取到的,所以关键问题是webview如何获取页面标题?
webview获取页面标题常用以下几种方案:
所以页面在加载完成后,触发了webview的pageload事件,在这个事件监听函数里获取页面title并更新显示到naviBar上。在单页应用生命周期中,因为页面切换并不像传统网页那样跳转->加载的模式,后续的页面切换就都没法再触发pageload事件,导致naviBar上显示的标题一直未更新。
还是那个问题,为什么通过iframe就可以?
其实答案很简单:我们知道iframe也是一种文档对象,所以iframe加载完成也能触发webview的pageload事件,让webview “认为” 页面更新了,所以就重新获取title并更新naviBar的显示。
done……
有兴趣的可以看看知乎上的回答:如何通过 js 修改微信浏览器的title?
参考资料:
一句话,在vscode的设置里加一句:
"terminal.integrated.shellArgs.osx": []
done!
function binarySearch(target, arr, low, high) {
let start = low === undefined ? 0 : low
let end = high === undefined ? arr.length - 1 : high
if (start > end) {
return -1
}
let mid = parseInt(start + (end - start) / 2)
if (arr[mid] === target) {
return mid
} else if (arr[mid] > target) {
return binarySearch(target, arr, start, mid - 1)
} else {
return binarySearch(target, arr, mid + 1, end)
}
}
function binarySearch(target, arr) {
let start = 0
let end = arr.length - 1
while(start <= end) {
mid = parseInt(start + (end - start) / 2)
if (target == arr[mid]) {
return mid
} else if (target > arr[mid]) {
start = mid + 1
} else if (target < arr[mid]) {
end = mid - 1
}
}
return -1
}
done!
const APP_ID = 'xxxx' // 这里写公众号的appid
const tempUrl = 'http://entpre2.slsai.com/home' // 这里写回调url,code会挂载在url上
const SCOPE = 'snsapi_base' // 授权形式,这里我采用静默授权
window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + APP_ID +
'&redirect_uri=' + encodeURIComponent(tempUrl) +
'&response_type=code&scope=' + SCOPE + '&state=STATE#wechat_redirect'
然后
页面自动跳转,url会长成这个样子:http://entpre2.slsai.com/home?code=xxxxxx&state=STATE
解释一下,这个state就是你之前要传的回调参数
然后你把code取出来,传给后端,后端一般会发起统一下单流程,并给你返回一些数据:如
未完待续……
项目中,经常会遇到实现文本溢出呈省略号,有的要求单行文本 ,有的要求多行文本,具体代码如下:
1、单行文本
div {
width: 100px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
}
2、多行文本
div {
width: 100px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 3;
overflow: hidden;
}
(因使用了WebKit的CSS扩展属性,该方法适用于WebKit浏览器及移动端)
注:
-webkit-line-clamp用来限制在一个块元素显示的文本的行数。 为了实现该效果,它需要组合其他的WebKit属性。常见结合属性:
display: -webkit-box; 必须结合的属性 ,将对象作为弹性伸缩盒子模型显示 。
-webkit-box-orient 必须结合的属性 ,设置或检索伸缩盒对象的子元素的排列方式 。
一脸懵逼中。。。
那么,现在就来从开始探索一下这道题的原理
js提供了三中不同的比较操作,分别是:
说一下几种操作的特点与不同。首先,使用=== 与Ojbect.is()进行比较时,是不会进行类型转换的,先判断两边的数据类型,如要两边的数据类型不同,就会直接返回false,再判断数据的值是否相同,这里有个坑点就是对于Number,=== 与Ojbect.is()在处理+0, -0, 与NaN方面有一些不同之处,如下
+0 === -0 // true
Object.is(+0, -0) // false
NaN === NaN // false
Object.is(NaN, NaN) // true
再来说一下==,这个因为涉及到了类型的转换,比较复杂一些。
可知:
1、Undefined 和 Null:一般情况下,他们只和自身及对方相等,其他情况都会返回false。有个IsFalsy()看起来很奇怪,对象不都应该是返回true么,有啥好判断的?还真不是……有些浏览器会允许一些特殊的对象,如:document.all 等,在某些情况下(相等操作符等)充当undefined的角色,所以,他就会返回false。都是坑爹呢这是……
2、Number: 想与Numbr进行对比,二话不说,你先转成number再BB
3、Boolean:刚想与Boolean做比较,额,他倒是先转成Number了,得嘞,走上了与Number比较的老路
4、Object:可能因为Object比较杂,所以需要先通过ToPrimitive()去找到他的真身以后再进行比较
5、String:优先级最低,因为留给他的对手不多了,一般都是被迫转型,除非对手是String或者ToPrimitive()是String
看起来,类型转换机制还挺复杂的,所以,一般情况下,能用 === 的就尽量不要用 == 了,免得掉进了自己的坑里。什么,非要用==不可?好吧,来看看一下几个案例:
"0" == false; // true
false == 0; // true
false == ""; // true
false == []; // true
"" == 0; // true
"" == []; // true
0 == []; // true
如果以上这些情况你都能理解,嗯,你可以放心的用==了。
最后,祝大家好运~
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.