Classic ASP.NET站点jQuery Widget的anItem无AJAX获取服务端数据问题
核心前提
你在(1)处声明的var anItem = el.anItem是引用类型赋值,只要后续this.options.anItem被修改,你后续访问anItem变量时都会拿到最新值,所以数据一定是在(1)到(2)的代码执行间隙被赋值到options上的。
可能的服务端数据获取途径
全局聚合JSON注入
很多老ASP.NET项目不会单独给每个变量写<%= %>注入,而是会把整页需要的所有业务数据序列化后一次性注入到全局变量中,比如:window.GlobalPageData = <%= Newtonsoft.Json.JsonConvert.SerializeObject(PageModel) %>;这类注入代码通常不会写在aspx页面的静态HTML里,大多是后端通过
ScriptManager.RegisterClientScriptBlock、ClientScript.RegisterStartupScript等方法动态注册到页面的,你直接搜前端静态文件找不到相关注入痕迹。其他公共脚本会在widget初始化后,把对应模块的数据从全局变量里取出来赋值给widget的options.anItem。DOM节点data属性缓存
你初始化widget的目标<div id="pnProcuringEntity">可能由服务端渲染时就携带了编码后的业务数据,比如:<div id="pnProcuringEntity" class='col-12 p-0' data-anitem="eyJjb250YWN0UG9pbnQiOnt9fQ==" />数据一般是base64编码的JSON,或者转义后的JSON字符串,widget内部或者公共的
translate方法在执行时会读取this.element.data('anItem'),解码后赋值给options.anItem,你可以打印原始节点的outerHTML确认是否存在相关自定义属性。jQuery全局数据缓存
老jQuery项目普遍使用$.data()接口存储全局公共数据,服务端会在页面加载初期动态输出脚本把业务数据写入全局缓存:$.data(document, 'TenderData', <%= JsonSerialize(Model) %>)widget执行过程中会主动从全局缓存中拉取对应模块的数据赋值给options。
本地缓存读取
如果站点存在同源的其他页面,可能提前把用户相关、业务相关的公共数据存在localStorage/sessionStorage中,widget执行时同步读取缓存数据赋值,不会触发服务端请求。
快速定位方法
在(1)位置的断点处执行以下代码劫持anItem的赋值操作,一旦值被修改就会打印完整调用栈,直接定位到赋值逻辑:
Object.defineProperty(this.options, 'anItem', { set: function(val) { console.trace('anItem 被赋值', val) this.__anItem = val }, get: function() { return this.__anItem } })
继续执行代码后查看控制台的调用栈,就能找到是哪段逻辑给anItem赋了值。
内容的提问来源于stack exchange,提问作者Alex

