vue内置组件keep-alive源码解析
vue内置组件keep-alive源码解析
很简单,我们直接看vue的源码即可。
keep-alive
组件支持三个属性。
props: {
include: patternTypes,
exclude: patternTypes,
max: [String, Number]
},
其中patternTypes = [String, RegExp, Array];
组件在created
周期时初始化自己的记录集合
created: function created () {
this.cache = Object.create(null); // 以组件实例的 key和vnode作为key-value存入其中
this.keys = []; // 存储组件实例的 key
},
在mounted
周期里面开始注册自己的watch
,watch自己的include
和exclude
属性进行pruneCache
。
mounted: function mounted () {
var this$1 = this;
this.$watch('include', function (val) {
pruneCache(this$1, function (name) { return matches(val, name); });
});
this.$watch('exclude', function (val) {
pruneCache(this$1, function (name) { return !matches(val, name); });
});
},
里面的几个辅助函数主要是用来比较组件是否需要缓存和操作缓存的。
function getComponentName (opts) {
return opts && (opts.Ctor.options.name || opts.tag) // 获取组件的名字或者tag
}
function matches (pattern, name) { // 支持多种格式的匹配
if (Array.isArray(pattern)) {
return pattern.indexOf(name) > -1
} else if (typeof pattern === 'string') {
return pattern.split(',').indexOf(name) > -1
} else if (isRegExp(pattern)) {
return pattern.test(name)
}
/* istanbul ignore next */
return false
}
function pruneCache (keepAliveInstance, filter) {
var cache = keepAliveInstance.cache; // 在keep-alive组件created时创建的
var keys = keepAliveInstance.keys; // 同上
var _vnode = keepAliveInstance._vnode;
for (var key in cache) {
var cachedNode = cache[key];
if (cachedNode) {
var name = getComponentName(cachedNode.componentOptions);
if (name && !filter(name)) {
pruneCacheEntry(cache, key, keys, _vnode);// 对于不符合include或exclude规则的组件实例调整对应的cache
}
}
}
}
function pruneCacheEntry (
cache,
key,
keys,
current
) {
var cached$$1 = cache[key];
if (cached$$1 && (!current || cached$$1.tag !== current.tag)) {
cached$$1.componentInstance.$destroy();
}
cache[key] = null; // 在cache对象和keys数组里面同步删除该key
remove(keys, key);
}
复杂点的部分就是render
了
render: function render () {
var slot = this.$slots.default;
var vnode = getFirstComponentChild(slot);
var componentOptions = vnode && vnode.componentOptions;
if (componentOptions) {
// check pattern
var name = getComponentName(componentOptions);
var ref = this;
var include = ref.include;
var exclude = ref.exclude;
if (
// not included
(include && (!name || !matches(include, name))) ||
// excluded
(exclude && name && matches(exclude, name))
) {
return vnode
}
var ref$1 = this;
var cache = ref$1.cache;
var keys = ref$1.keys;
var key = vnode.key == null
// same constructor may get registered as different local components
// so cid alone is not enough (#3269)
? componentOptions.Ctor.cid + (componentOptions.tag ? ("::" + (componentOptions.tag)) : '')
: vnode.key;
if (cache[key]) {
vnode.componentInstance = cache[key].componentInstance; // 直接使用缓存里面的组件实例
// make current key freshest // 在原位置移除再重新推入,确保key在keys最后面(即最新的)
remove(keys, key);
keys.push(key);
} else {
cache[key] = vnode;
keys.push(key);
// prune oldest entry
if (this.max && keys.length > parseInt(this.max)) {
pruneCacheEntry(cache, keys[0], keys, this._vnode);
}
}
vnode.data.keepAlive = true;
}
return vnode || (slot && slot[0])
}
- 分类:
- Web前端
相关文章
2021年的一点工作总结(一)迁移React技术栈
2021年全年的工作总结起来很简单,算是做苦力的一年吧。。。 2021年春节后就开始邮件项目从Vue迁移到React的工作以及富文本编辑器由wangEditor替换成CKEditor。 其实自己 阅读更多…
从vuecli3学习webpack记录(一)vue-cli-serve机制
最近看了看vuecli3,把自己的学习记录下来。 首先看入口 npm run dev 即是 vue-cli-service serve ,之所以能运行 vue-cli-service 命令,就是 阅读更多…
el-table实现动态列el-table-column
element-ui的官网有el-table实现自定义表头的demo,没错,实现动态列就是用的这个。 假设我们有个这样的添加动态列的需求:将班上的同学(人数不固定)的各科成绩根据姓名横向展示出来 阅读更多…
element-ui表单源码解析之el-input
关于表单校验el-input做的主要工作就是跟el-form-item交互,把input的相关事件发送给el-form-item,上一篇已经讲到在el-form-item的mounted的生命周期里 阅读更多…
Vue2.6.10源码分析(一)vue项目怎么神奇的跑起来的
先看index.html的代码吧 <!DOCTYPE html> <html lang="en"> <head> <meta 阅读更多…
前端框架vue+wordpress做后端
目前正在利用闲暇时捯饬一下自己的博客,毕竟这么久没有维护了,wordpress是可以用restful API来获取数据的,决定前端用vue实现,目前正在尝试中,今天做了其中很小的一部分,就是博客目录 阅读更多…