最近开始看尤雨溪大神的vue源码,这算是开篇吧。打算从第一个版本开始,一个一个开始看,将看到的收获记录下来,也好督促自己坚持下去。
适用场景:大家都知道js是单线程的,而一些不是很重要的任务,为了不影响主要逻辑的运行,可以放在线程空闲后执行。譬如我之前遇到过的日志记录,可以等待页面渲染完成后再向后台发送请求。
因为看的是第一个版本,版本号是a879ec0。从源码中删除了一些跟本主题无关的代码,如下:
var nextTick = (function () {
// 保存回调方法的队列
var callbacks = []
// 这个变量很值得玩味,下面解释
var pending = false
// 如果支持setImmediate方法则使用,不支持则用setTimeout
// setImmediate是微软开发的,IE10以上支持,这里不详细解释,因为我也不是很懂,哈哈
var timerFunc = window.setImmediate || setTimeout;
// 执行回调方法队列
function nextTickHandler () {
// 置为false,以后可以创建新的任务
pending = false
// 复制队列,用这个方法复制确实不错,高效
var copies = callbacks.slice(0)
// 清空原有队列
callbacks = []
for (var i = 0; i < copies.length; i++) {
copies[i]()
}
}
return function (cb, ctx) {
// cb 任务方法
// ctx cb的执行环境
var func = ctx
? function () { cb.call(ctx) }
: cb
// 压入队列
callbacks.push(func)
// pending为true,表示任务已经创建
// pending为false,任务没创建,需要创建
if (pending) return
pending = true
// 创建任务
timerFunc(nextTickHandler, 0)
}
})();
setTimeout会在线程空闲时立刻执行任务队列。
这里的任务方法没有添加参数,因为在该版本中没有这个必要,这里我小小修改了一下
var nextTick2 = (function () {
var callbacks = []
var pending = false
var timerFunc = window.setImmediate || setTimeout;
function nextTickHandler () {
pending = false
var copies = callbacks.slice(0)
callbacks = []
for (var i = 0; i < copies.length; i++) {
copies[i]()
}
}
return function (cb, ctx ,args) {
var func = ctx
? function () { cb.call(ctx,args) }
: function () { cb(args) };
callbacks.push(func)
if (pending) return
pending = true
timerFunc(nextTickHandler, 0)
}
})();
这样将参数args传入就能执行了。
当然这还只是vue的第一个版本,很多东西我还是看的云里雾里,整个结构还没有梳理成型,和大神的差距好大啊啊啊啊。。。。
后续版本如果有更好的解决方案我会继续更新。
本文内容纰漏之处请各位指正,谢谢!
祝爸爸妈妈身体健康!
网友评论