如何在Dojo的REST Tree中禁用缓存?附完整复现代码
解决Dojo JsonRestStore树节点名称不更新的缓存问题
你碰到的这个问题我之前也遇到过——确实是dojox.data.JsonRestStore的内部引用缓存在搞鬼!当节点用$ref标识时,Store会把第一次加载的节点数据缓存起来,哪怕后续REST接口返回了新的名称,它也直接复用缓存里的对象,根本不更新属性。下面给你几个靠谱的解决办法:
方法1:全局禁用JsonRestStore的对象缓存
最简单的方式就是在初始化Store时直接关闭默认缓存,同时确保查询请求也禁用缓存:
this.store = new dojox.data.JsonRestStore({ target: 'reproducing-REST.php', labelAttribute: "name", cacheByDefault: false // 全局关闭默认缓存 });
同时在Tree的Model配置里明确添加查询级的缓存禁用:
this.model = new dijit.tree.ForestStoreModel({ store: this.store, deferItemLoadingUntilExpand: true, rootId: "products", rootLabel: "Products", query: { queryOptions: { cache: false } }, // 确保查询不使用缓存 childrenAttrs: ['children'] });
方法2:手动清除Store的内部缓存
如果不想全局禁用缓存,可以在刷新树之前,手动清除Store里存储$ref对应对象的_index缓存:
function refresh2() { // 新增:清除Store的内部缓存 if (prod.store && prod.store._index) { for (var key in prod.store._index) { delete prod.store._index[key]; } } // 原有销毁重建逻辑不变 delete prod.tree; delete prod.model; delete prod.store; dijit.byId('products_tree').destroy(true); prod.init(); prod.tree = new dijit.Tree({ model: prod.model, query: {queryOptions:{preventCache:true}}, persist: false }, 'products_tree'); prod.tree.startup(); }
方法3:更新缓存对象属性(推荐)
如果想保留缓存优势同时更新名称,可以监听Store的onItemLoad事件,手动同步缓存对象的属性并触发Tree更新:
this.store = new dojox.data.JsonRestStore({ target: 'reproducing-REST.php', labelAttribute: "name" }); // 监听节点加载事件,同步更新缓存对象的名称 dojo.connect(prod.store, "onItemLoad", function(item, request) { var newName = prod.store.getValue(item, "name"); if (item.name !== newName) { item.name = newName; // 通知Tree模型数据变化,刷新节点UI prod.tree.model.onChange(item); } });
为什么你的refresh2方法无效?
你之前的refresh2只是销毁了Tree、Model和Store实例,但JavaScript内存里之前缓存的节点对象还存在。重新创建Store时,JsonRestStore会复用相同$ref对应的缓存对象,所以必须显式清除缓存或者禁用缓存机制。
修改后的复现代码
reproducing_problem.php
<?php if(!isset($_SESSION)) { session_start(); } $_SESSION['keyA']=0; ?> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>Reproducing Cache Problem</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <!--META HTTP-EQUIV="CACHE-CONTROL" CONTENT="NO-CACHE"--> <script type="text/javascript" src="../external/dojo/dojo.js" djConfig="parseOnLoad: true"></script> <script type="text/javascript"> dojo.require('dojox.data.JsonRestStore'); dojo.require('dijit.Tree'); dojo.require("dijit.form.Button"); var prod= { store: null, model: null, tree: null, init: function() { this.store = new dojox.data.JsonRestStore({ target: 'reproducing-REST.php', labelAttribute: "name", cacheByDefault: false // 新增:全局禁用缓存 }); this.model = new dijit.tree.ForestStoreModel({ store: this.store, deferItemLoadingUntilExpand: true, rootId: "products", rootLabel: "Products", query: {queryOptions:{cache:false}}, // 新增:查询禁用缓存 childrenAttrs: ['children'] }); } }; function refresh1() { tree=prod.tree tree._itemNodesMap = {}; tree.rootNode.state = "UNCHECKED"; tree.model.root.children = null; if (tree.rootNode) { tree.rootNode.destroyRecursive(); } tree._load(); } function refresh2() { // 新增:清除Store内部缓存 if (prod.store && prod.store._index) { for (var key in prod.store._index) { delete prod.store._index[key]; } } delete prod.tree; delete prod.model; delete prod.store; dijit.byId('products_tree').destroy(true); prod.init(); prod.tree = new dijit.Tree({ model: prod.model, query: {queryOptions:{preventCache:true}}, persist: false }, 'products_tree'); prod.tree.startup(); } dojo.addOnLoad(function() { prod.init(); prod.tree = new dijit.Tree({ model: prod.model, persist: false }, 'products_tree'); prod.tree.startup(); }); </script> <style type="text/css"> @import "../external/dijit/themes/soria/soria.css"; @import "../external/dojo/resources/dojo.css"; </style> </head> <body class="soria"> <div dojoType="dijit.form.Button"> Change name and refresh <script type="dojo/event" event="onClick"> refresh1(); </script> </div> <div id="products_tree"></div> <div id="notes">notes</div> </body> </html>
reproducing-REST.php
<?php if(!isset($_SESSION)) { session_start(); } $keyA=$_SESSION['keyA']; $_SESSION['keyA']=$keyA+1; if (array_key_exists('PATH_INFO', $_SERVER)) { $arr = null; $resource = $_SERVER['PATH_INFO']; $method = $_SERVER['REQUEST_METHOD']; error_log(" resource: ".$resource." \n",3,"mylogfile.txt"); if ($method == 'GET') { if ($resource=='/'){ $arr=array(); $sameref='1234'; $name="Changing".$keyA; error_log(" name: ".$name." \n",3,"mylogfile.txt"); array_push($arr,array('$ref' => $sameref, 'name' => $name, 'children' => true)); } else{ $aProduct = ltrim($resource, '/'); $arr=array(); $name="exploding"; $child='2345'; array_push($arr,array('name' => $name,'idq' => $child)); $arr=array('idp' => $aProduct, 'name' => $name, 'children' => $arr); } $status = 'HTTP/1.1 200 OK'; } header($status); echo json_encode($arr); } ?>
内容的提问来源于stack exchange,提问作者Paul Ghobril
相关产品推荐
相关产品推荐

