道招

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自己的includeexclude属性进行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])
}
更新时间:
上一篇:以webpack为例来看微内核架构下一篇:Javascript去除内容格式并匹配目标格式粘贴

相关文章

element-ui表单源码解析之el-input

关于表单校验el-input做的主要工作就是跟el-form-item交互,把input的相关事件发送给el-form-item,上一篇已经讲到在el-form-item的mounted的生命周期里 阅读更多…

el-table实现动态列el-table-column

element-ui的官网有el-table实现自定义表头的demo,没错,实现动态列就是用的这个。 假设我们有个这样的添加动态列的需求:将班上的同学(人数不固定)的各科成绩根据姓名横向展示出来 阅读更多…

命令式组件Message、Dialog的主流写法分析

这里还是以element-ui为例,那我们就看看里面的Message。 它的dom结构什么的就写在node-modules/element-ui/packages/notification/src/ 阅读更多…

用个数组来理解vue的diff算法(一)

原文地址: 道招网 的 用个数组来理解vue的diff算法(一) Vue使用的diff算法,我相信用vue的估计都听过,并且看到源码的也不在少数。 先对下面的代码做下说明: 由于这里用 阅读更多…

前端框架vue+wordpress做后端

目前正在利用闲暇时捯饬一下自己的博客,毕竟这么久没有维护了,wordpress是可以用restful API来获取数据的,决定前端用vue实现,目前正在尝试中,今天做了其中很小的一部分,就是博客目录 阅读更多…

vue多语言的解决方案不只是 vue-i18n,前端+后端完整解决方案

网上搜很多vue多语言的,一般都是介绍vue-i18n怎么使用,当然这是不错的,但是我们如果只是讲这个的话,只是解决了静态文字的多语言化。 这一部分我们也简单讲一下 npm install 阅读更多…

关注道招网公众帐号