首页 > 代码库 > 【Lua】Lua + LWT + ExtJS构建目录树

【Lua】Lua + LWT + ExtJS构建目录树

  Lua处理后台逻辑,Lua lwt搭建后台程序,ExtJS根据后台传来的json数据构建目录树。


  前台html和ExtJS代码不用多讲,直接上代码:

  treePanel.html

 1 <html> 2     <head> 3         <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 4          5         <title>ExtJS TreePanel</title> 6         <link rel="stylesheet" type="text/css" href="../../ext-5.0.0/examples/shared/example.css" /> 7          8          9         <script type="text/javascript" src="../ext-5.0.0/examples/shared/include-ext.js"></script>10         <script type="text/javascript" src="../ext-5.0.0/examples/shared/options-toolbar.js"></script>11         12         <script type="text/javascript" src="treePanel.js" charset="utf-8" ></script>13   14     </head>15     <body style=" margin: 0; padding: 0;">16     </body>17 </html>

  treePanel.js

 1 Ext.require(‘Ext.tree.Panel‘) 2  3 Ext.onReady(function(){     4     Ext.Ajax.request({ 5         url: ‘treePanel.lua‘,    6         method: ‘post‘, 7         params: { 8             id: "123", 9             action: ‘getDir‘10         },11         success: function(response){12             var text = response.responseText; 13             var obj = eval(‘(‘ + text + ‘)‘); 14             var treePanel = Ext.create(‘Ext.tree.Panel‘,{15                 width: 200,16                 rootVisible: false,17                 store: obj,18                 renderTo: Ext.getBody(),19             });      20         }, 21         failure: function() {22             Ext.Msg.alert("失败","失败了");23         }24     });25 });

  在treePanel.js中,通过后台传递过来的json字符串无法直接使用,需要将其转化为json对象才可以作为treePanel的数据源。

  转换方法:jsonObj = eval(‘(‘+jsonString‘+)‘)


  接下来是逻辑处理部分,也就是遍历目录数据的部分。

  一开始我使用的方法是先将所有文件path遍历至一个table内,然后处理table将其转化为treePanel可以用的json格式,这样遍历过程比较简单,不过处理过程太过繁琐,处理方法结构脆弱且BUG不断,效率也是惨不忍睹。最后还是放弃了。

  其实最合适的方法是直接在遍历时就生成所需要的json格式,好吧,现在就来实现他:

  lua遍历目录需要达成的格式为:

 1 local s = {root = {  2         text = "rootNode", 3         expanded = true, 4         leaf = false, 5         children = { 6             { 7                 text = book1, 8                 leaf = false, 9                 children = nil10             },11             {12                 text = "book2",13                 leaf = false,14                 expanded = true,15                 children = {16                     {17                         text = "con1",18                         leaf = false,19                         children = {20                           {21                             text = "ccc1",22                             leaf = true23                           }24                         }25                     },{26                         text = "con2",27                         leaf = true28                     }29                 }30             },31             {32                 text = "book3",33                 expanded = true,34                 leaf = true35             }36         }37     }38 }

  用lfs模块提供的方法遍历目录,并创建一个table,操作table使之成为这样的结构。其中:

    "leaf = true"表示这个节点是一个文件,所以不必加上"children = {}"属性;

    如果节点是一个文件夹,那给节点设置"leaf = false"表示为文件夹(如果不设置这个属性默认为文件夹,不过这里用来作为判断的条件,所以加上),并且加上"children = {}" 用来作为该文件夹下文件的根节点。

  方法getDirTable(filePath)用以遍历目录,并生成指定的table结构数据:

 1 function getDirTable(filePath) 2     local table = {root = {text = "rootNode", leaf = false, children = {}}} 3     function getDir(path,table) 4         for file in lfs.dir(path) do 5             if file ~= "." and file ~= ".." then 6                 p = path .. "/" .. file 7                 if isDir(p) == "directory" then 8                     local node = {text = file, leaf = false, children = {}} 9                     table[#table + 1] = node                   10                     local nObj = table[#table].children11                     local nPath = path .. file .. "/"12                     getDir(nPath, nObj)13                 else 14                     local node = {text = file, leaf = true}15                     table[#table + 1] = node16                 end17              end   18         end19     end20     getDir(filePath,table.root.children) 21     return table22 end

  其中遍历了当下文件夹,如果文件夹下存在子文件夹,则递归遍历子文件夹,并且将子文件夹下的文件和文件夹依照规则添加到该文件夹节点的"children = {}"内。

  在这个方法中,还有一个辅助方法,用来判断path是文件还是文件夹:

1 function isDir(path)2    return lfs.attributes(path).mode3 end

  获取目录遍历table后,使用cjson方法转换为json字符串:

1 function table2Json(table)2     local cjson = require("cjson")3     return cjson.encode(table)4 end

  最后通过lwt将json字符串传到前台:

1 httpd.set_content_type("text/json") 2 if request.method == "POST" then3     if args.action == "getDir" then4         httpd.write(table2Json(getDirTable(request.filedir)))5     end6 elseif request.method == "GET" then7     httpd.write("是个字符串")8 end

  完整代码:

 1 require "lfs" 2 require "httpd" 3  4 request, args = ...  5  6 function isDir(path) 7    return lfs.attributes(path).mode 8 end 9 10 function table2Json(table)11     local cjson = require("cjson")12     return cjson.encode(table)13 end14 15 function getDirTable(filePath)16     local table = {root = {text = "rootNode", leaf = false, children = {}}}17     function getDir(path,table)18         for file in lfs.dir(path) do19             if file ~= "." and file ~= ".." then20                 p = path .. "/" .. file21                 if isDir(p) == "directory" then22                     local node = {text = file, leaf = false, children = {}}23                     table[#table + 1] = node                   24                     local nObj = table[#table].children25                     local nPath = path .. file .. "/"26                     getDir(nPath, nObj)27                 else 28                     local node = {text = file, leaf = true}29                     table[#table + 1] = node30                 end31              end   32         end33     end34     getDir(filePath,table.root.children) 35     return table36 end37 38 httpd.set_content_type("text/json") 39 if request.method == "POST" then40     if args.action == "getDir" then41         httpd.write(table2Json(reTable(getDirTable(request.filedir))))42     end43 elseif request.method == "GET" then44     httpd.write("GET请求")45 end

  访问treePanel.html

  这里有一个问题,看asd.sda文件夹下

 

  这里出现了一个没有名字的空文件夹。这是由于遍历时,检测到是目录时默认给其赋值了"children = {}"的缘故,由于在treePanel中,当不设置"leaf: true"时,默认leaf为false,即将其认为是一个文件夹。所以ExtJS给这个文件夹节点添加了一个没有名字的空子文件夹。

  要解决这个问题,只要将为空的文件夹设置为children = nil,这样就可以了。

 1 function reTable(table) 2     local obj = table.root.children 3     function re(obj) 4         if #obj == 0 then 5             obj = nil 6         else 7             for i = 1, #obj do 8                 if obj[i].leaf == false then 9                     if #(obj[i].children) == 0 then10                         obj[i].children = nil11                     else12                         re(obj[i].children)13                     end14                 end15             end16         end17     end18     re(obj)19     return table20 end

  最后把lwt响应改一下:

httpd.write(table2Json(reTable(getDirTable(request.filedir))))

  看看效果:

  这样就显示了一个空文件夹,问题解决!

【Lua】Lua + LWT + ExtJS构建目录树