我会在 Liferay Portal 中使用全局 AngularJS。因为,就像 AngularJS 的设计:
Why AngularJS? HTML is great for declaring static documents, but it falters when we try to use it for declaring dynamic views in web-applications. AngularJS lets you extend HTML vocabulary for your application. The resulting environment is extraordinarily expressive, readable, and quick to develop.
我会通过开发 Liferay-Theme 和 Portlets 来简单地使用 html 的声明性语法。
为了这个需求,我创建了新的 Liferay-Theme 并定制了一点
portal_normal.vm
:<!DOCTYPE html>
<#include init />
<html ... ng-app="liferay">
<head>
...
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.8/angular.min.js"></script>
<script type="text/javascript" src="${javascript_folder}/my.js" charset="utf-8"></script>
</head>
<body class="${css_class}">
<div ng-controller="LiferayCtrl">
这里
my.js
:angular.module('liferay', [])
.controller('LiferayCtrl', function($scope) {
console.log("---==== Init AngularJS ====---");
$scope.Liferay = Liferay;
});
我可以扩展 Controller ,比如获取 Liferay-Site 名称。
这一切有什么帮助?
因此,我可以通过声明性 html 语法简单地访问 Liferay JavaScript 值和函数,而无需像 AngularJS 那样直接调用 JavaScript 函数。
例如。现在可以通过声明性的 html 代码来获取 Liferay JavaScript 的值和函数,如下所示,用于在 Web 内容显示中获取当前 url:
Liferay current URL: {{Liferay.currentURL}}
但是,我的问题是:
最佳答案
首先:在门户本身上使用 AngularJS 的好主意。到目前为止,我们仅将 AngularJS 用于 portlet——稍后我将解释原因和方法。
可能的副作用和冲突
与其他 JavaScript 库或框架相比,使用 AngularJS 不会有更多的副作用。 Liferay 与 AlloyUi ( http://alloyui.com/ ) 一起提供。这个 JavaScript 库基于 yahoo 编写的 YUI ( http://yuilibrary.com/ )。 YUI 使用与 jQuery 不同的命名空间,因此您可以将 jQuery 与 AlloyUI 一起使用。如果您能够在没有任何副作用的情况下使用 jQuery,您可能会更多地使用 AngularJS,因为 AngularJS 提供了 jQuery 的一个子集。
如果您不仅需要 AngularJS 的 jqLite 实现,还需要完整的 jQuery,那么您必须确保在 AngularJS 之前包含 jQuery。这可以通过更改 portal_normal.vm
轻松完成。在您的主题中:
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>$the_title - $company_name</title>
<script type="text/javascript" src="$javascript_folder/jquery-2.0.3.min.js" charset="utf-8"></script>
<script type="text/javascript" src="$javascript_folder/angular-1.2.7.min.js" charset="utf-8"></script>
$theme.include($top_head_include)
</head>
如果您在主题级别包含 JavaScript 文件,您就可以为每个主题使用不同的版本。如果您有多个门户实例并且您没有机会在每个实例中使用相同的版本,这将非常方便。
表现
这取决于。必须知道,如果您输入
ng-app
,Angular 将解析整个网页。 html 元素上的指令,如您的示例所示。如果您的页面非常大并且有很多内容,则可能是性能问题。因此,最好将 ngApp 指令放在页面中,并通过以下方式手动初始化 ngApp:$().ready(function() {
angular.bootstrap("css-selector", ['yourApp']);
});
在 portlet 中使用 AngularJS
有两种方法可以实现这一点。
1)在您的示例中的大型 ngApp 上。你必须知道,你不能嵌套 ngApps。因此,每个 portlet 都必须是您的应用程序的一部分。使用这种方法,您将失去 portlet 可以为您的页面提供单独部分的可能性。所有 portlet 都需要知道您的 ngApp 的名称,并且必须扩展这个 ngApp。如果这些 portlet 使用另一个 ngApp 名称或没有使用其他门户服务器名称,则您不能在没有更改的情况下使用这些 portlet。优点是可以分享
$rootScope
在您的所有 portlet 中,这些 portlet 可以以 Angular 方式相互通信(例如 $emit
、 $on
、共享服务等)。2) 每个 portlet 都有自己的 ngApp。在这种情况下,没有依赖关系。每个 portlet 都可以通过
angular.bootstrap
实例化自己的 ngApp .此外,每个 ngApp 只为网页的一小部分创建,并且仅在确实需要时才创建。在这两种方式中,您都应该避免使用路由。因为只有一个
routeProvider
可以每页使用。我们决定使用第二种方法,以便 portlet 保持独立并且不依赖于全局 ngApp。
有用的提示——我希望
Portlet 配置
您知道您可以配置您的 portlet。所以问题出现了:“我如何为我的 angular portlet 提供我的 portlet 首选项?”当然,您可以发出 http 请求来获取它们。但这还不够,因为您拨打了不必要的电话。您的 portlet 通常是 java 服务器页面,因此最好在服务器上的生成期间包含首选项并将这些信息提供给您的 angular 应用程序。但是如何?
在
doView
使用您的 portlet 的方法,您可以创建一个 JSON 对象并将其存储在您的 RenderRequest
中的一个键下。 :public void doView(RenderRequest renderRequest, RenderResponse renderResponse) throws IOException, PortletException {
PortletPreferences prefs = renderRequest.getPreferences();
Map<String, Object> values = new HashMap<String, Object>();
values.put(key, value);
renderRequest.setAttribute("config", new ObjectMapper().writeValueAsString(values));
super.doView(renderRequest, renderResponse);
}
在您的 jsp 中,您可以访问此配置属性:
<div class="hidden" portlet-config>${config}</div>
portlet-config
是一个解析 JSON 并将信息存储在服务实例中的指令:.factory('portletConfigService', function(){ return {}})
.directive('portletConfig', ['portletConfigService', function(portletConfigService) {
return {
restrict: 'A',
compile: function(elem, attrs) {
var config = angular.fromJson(elem.text());
angular.forEach(config, function(value, key){
portletConfigService[key] = value;
});
}
};
}])
现在您可以注入(inject)
portletConfigService
到每个 Controller 、服务、工厂或其他任何地方,并使用配置参数:portletConfigService.key
.语言属性
我们遇到的另一个问题是语言属性。通常你会在
language.properties
中定义它们文件并在您的 jsp 中使用它们。例如通过 fmt:message
标签。但是您也希望能够在您的 angular js 应用程序中访问它们。而你绝对不想要的是在你的来源中有两次。我们通过生成的服务和指令解决了这个问题,该指令读取当前用户语言的属性并在 jsp 中创建 Angular 内容:<%@page contentType="text/javascript; charset=UTF-8" %>
<%@ page import="java.util.ResourceBundle" %>
<%@ page import="java.util.Locale" %>
<%@ page import="java.util.Enumeration" %>
<%@ page import="org.apache.commons.lang.StringEscapeUtils" %>
angular.module('translations', [])
.factory('translations', function(){ return {
<%
ResourceBundle labels = ResourceBundle.getBundle("language", request.getLocale());
Enumeration<String> keys = labels.getKeys();
while(keys.hasMoreElements()){
String key = keys.nextElement();
out.write("\""+key+"\":\""+StringEscapeUtils.escapeJavaScript(labels.getString(key))+"\"");
if(keys.hasMoreElements()){
out.write(",\n");
}
}
%>
}})
.filter('mpbtranslate', ['translations', function(translations) {
return function(input) {
var translation = translations[input];
return translation? translation: '???'+input+'???';
};
}]);
您现在可以将这些翻译用作服务和过滤器。例如
<div>{{'title' | translate}}</div>
例如,将在客户端评估为“Titel”。我希望你能得到一些关于你的担忧的有用信息。
关于javascript - 在 Liferay 中使用 AngularJS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21140580/