记录 UmiJs Model-namespace 不能重名问题

16 篇文章 0 订阅
1 篇文章 0 订阅

背景:

部分项目目录结构:
		page文件夹
			a文件夹
				models文件夹
					comModel.js
			b文件夹
				models文件夹
					comModel.js

问题:
comModel.js同名导致的问题:页面挂载完成,接口无法请求;重新刷新页面,接口正常请求

查询官网
只有 model的注册说明,并无 namespace 属性详细说明,如图:
在这里插入图片描述
按照官网的说明,page model 在 production 时按需载入,在 development 时全量载入,page model会向上查找;所以我理解为:将路由切换到当前层级b下的page时,model会按照层级向上查找,绝不会找a层级里面的model文件,即使有重名的,应该会进行覆盖;但是实际操作时却不是这样,从 a 层级切换到 b 层级时,控制台 g_app 对象(一个全局的app对象,里面包含_model,路由等各种全局信息)打印出来的 _models属性(数组,包含全局的model数据)中依旧是a层级的model数据,这个时候我感觉不太对,决定去github上看看

g_app结构如下图:
在这里插入图片描述
g_app -> _models 数据结构如下图:
在这里插入图片描述

查看 github issues
通过查询 github 上,umijs 的 issues,发现确实有 namespace 重复的相关问题,但得到的大多数答案都是 umijs 不支持同名 namespace ,在 3.x版本之后,会有 namespace 重复 的警告提示,建议修改 namespace 名称。官方文档中提到 namespace 是全局 state中的一个属性,所以我就觉得,既然没有这方面的相关处理(比如:层级隔离,重名覆盖等),那源码中会不会使用 namespace 这个属性做了什么全局的处理?比如:如果namespace相同,就不更新。于是先修改了 namespace 使期全局唯一,保证项目正常运行,接下来去查看源码验证自己的猜想。

阅读源码
刚开始直接从 umijs 里面找_model -> namespace,有零星的查找结果,但都是压缩过的代码,结果不理想,这时感觉查找方向不对,突然想起 umijs 集成了 dva.js, 所以转向从 dva.js 里面查找,果然找到了,里面有大量 namespace相关操作,源码中关于model替换的核心代码如下:

/**
	   * Replace a model if it exsits, if not, add it to app
	   * Attention:
	   * - Only available after dva.start gets called
	   * - Will not check origin m is strict equal to the new one
	   * Useful for HMR
	   * @param createReducer
	   * @param reducers
	   * @param unlisteners
	   * @param onError
	   * @param m
	   */


	  function replaceModel(createReducer, reducers, unlisteners, onError, m) {
	    var store = app._store;
	    var namespace = m.namespace;
	    var oldModelIdx = (0, utils$2.findIndex)(app._models, function (model) {
	      return model.namespace === namespace;
	    });

	    if (~oldModelIdx) {
	      // Cancel effects
	      store.dispatch({
	        type: "".concat(namespace, "/@@CANCEL_EFFECTS")
	      }); // Delete reducers

	      delete store.asyncReducers[namespace];
	      delete reducers[namespace]; // Unlisten subscrioptions

	      (0, subscription.unlisten)(unlisteners, namespace); // Delete model from app._models

	      app._models.splice(oldModelIdx, 1);
	    } // add new version model to store


	    app.model(m);
	    store.dispatch({
	      type: '@@dva/UPDATE'
	    });
	  }

从注释当中可以看到,Will not check origin m is strict equal to the new one 不会严格对比model数据,代码中也只是使用 namespace 做了比较 return model.namespace === namespace,并没有深入比较对象中其他属性;如果namespacec相同就不会覆盖替换,而是保留原有的model。如果刷新页面,那么全局的 state(_models) 就会失去现有数据,按照现有的路由进行更新,所以才导致刷新页面会正常请求的现象。

总结
从发现问题到得出结论,整个过程虽然不是很顺利,但是让自己对这个库又有了深入的了解,也是一种收获。也验证了自己的猜想是对的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值