在Java Web Project中實現Vue異步組件加載
最近看上了ElementUI(Vue實現)用來實現一個管理系統Demo,其中一個最常見的需求就是左側導航不動,右側主頁塊在點擊導航菜單時動態更新,如下圖所示:
之前的實現方案是右邊嵌入一個iframe,動態更改iframe的url即可,現在既然用了Vue咱也試試單頁,是不是顯得更優雅。接著就接觸到了vue-router、組件、異步組件這些關鍵字,本以為把頁面定義為xxx.vue放到webapp下,然後告訴vue-router去加載就好了,最後發現自己想簡單了,思維模式還停留在Java Web開發上,感覺Vue這類框架更多適用於純前端開發者或Node環境?按照官方文檔的說法“結合 Vue 的異步組件和 Webpack 的代碼分割功能,輕松實現路由組件的懶加載。”在 Webpack 的加持下貌似可以達到要求,但是這又是一個什麽鬼?暫時粗淺的認為它是一個工具,可以解析.vue生成.js。難道說我要把前端部分單獨出來,然後每次寫完先 Webpack 一下,再把生成的文件拷貝到webapp下?這對於目前的模式來說肯定是不可行的,且不說前後端分離帶來的部署調試的麻煩,首先分離後就喪失了Spring+Thymeleaf的優勢,其次目前的情況分不分都是一個人玩,從前寫到後,切來切去多累,我只想在一個Eclipse 的 Project 中解決問題,怎麽辦?
實現思路
後來研究了Vue的異步組件,發現它要的無非就是一段定義組件的JS代碼,那麽完全可以定義一個接口來輸出JS代碼。把一個Vue組件拆分成兩個同名文件如:user_list.js user_list.html(user_list就是組件名稱,本來一個js就足夠了,但是為了避免在js中寫HTML字符串還是分開好,js中的template屬性用一個占位符便於替換如:template: ‘$template‘)放在WEB-INF/vue-component下,然後實現接口,這個接口收到請求自動把兩個文件拼合為一段JS代碼,響應給前端,代碼如下:
@GetMapping("/vcp") public void parse(@RequestParam("p") String path, HttpServletRequest req, HttpServletResponse resp) throws IOException { if(StringUtils.isEmpty(path)) return; String res = "null"; String vcpDir = req.getServletContext().getRealPath("/WEB-INF/vue-component/"); File jsFile = new File(vcpDir + path + ".js"); File htmlFile = new File(vcpDir + path + ".html"); if(jsFile.exists() && htmlFile.exists()) { String jsCode = BaseUtils.readCodeFileAsText(jsFile); String htmlCode = BaseUtils.readCodeFileAsText(htmlFile); res = "window.vcpRes[‘"+path+"‘] = "+jsCode.replace("$template", htmlCode); } // response resp.setContentType("application/x-javascript;charset=utf-8"); PrintWriter out = resp.getWriter(); out.println(res); out.close(); }
接口定義好了再來看Vue部分(下面給出關鍵性代碼,關鍵是思路,版本信息:vue2.5 vue-router3.0)
// 定義全局變量,用於接收接口輸出的JS組件對象 window.vcpRes = {}; // 添加路由 routes.push({path: ‘/user/list‘, component: Vue.component(‘user-list‘, syncComponent(‘user_list‘)) }); /** * 該函數通過JQuery異步獲取組件,path參數就是組件名如:user_list */ function syncComponent(path){ return function(resolve, reject){ $.getScript(‘vcp?p=‘+path, function(){ var component = window.vcpRes[path]; if(component){ resolve(component); }else{ reject(‘組件加載失敗:‘+path); } }); }; }
結語
如果有時間,也可以在接口中實現一個.vue的解析器,這樣組件就不用分兩個文件寫了。這只是我個人能想到的一種解決方案,能力有限。如果你是一名Java Web開發者也在使用Vue,有更好的解決方案請留言。
在Java Web Project中實現Vue異步組件加載