JSF页面中的JS取得受管bean的数据(受管bean发送数据到页面)

  JSF中引入jsf.js文件之后,可以拦截jsf.ajax.request请求。一直希望有一种方法可以像jquery的ajax一样,能在js中异步取得服务器端发送的数据。无奈标准JSF并没有提供这样的方法。在一些JSF框架里面提供了这样的方法,比如primefaces的onComplete方法就是返回数据到一个js方法中的。JSF能在bean里面更新视图(非ajax更新),其中的PartialViewContext类就可以做到局部更新UI,在bean里获取到这个UI就可以了。于是在网上翻看了很多开源的JSF框架,无意中发现omnifaces这个开源框架。官网:http://omnifaces.org/。

  当然,一个框架的东西会有很多,以个人之力要全部参透会有一些难度。开源框架更是集思广益,不过我所需要的只是其中的一部分而已,即在js中取得bean返回的数据。

  根据omnifaces的showcase http://showcase.omnifaces.org/ 看到其中的一个Ajax工具类根据PartialViewContext类做到了js取得返回数据,不论字符串或者对象数据都可以发送,非常方便。于是根据提供的源码,顺藤摸瓜,copy了必须支持的类,整理出来了一个仅Ajax发送数据的jar。

  omnifaces做的步骤大概是先重写了PartialViewContextFactory这个类,然后在配置文件中配置该重写的类。

  

 1 /**
 2  * This partial view context factory takes care that the {@link OmniPartialViewContext} is properly initialized.
 3  *
 4  */
 5 public class CustomPartialViewContextFactory extends PartialViewContextFactory {
 6
 7     // Variables ------------------------------------------------------------------------------------------------------
 8
 9     private PartialViewContextFactory wrapped;
10
11     // Constructors ---------------------------------------------------------------------------------------------------
12
13     /**
14      * Construct a new OmniFaces partial view context factory around the given wrapped factory.
15      * @param wrapped The wrapped factory.
16      */
17     public CustomPartialViewContextFactory(PartialViewContextFactory wrapped) {
18         this.wrapped = wrapped;
19     }
20
21     // Actions --------------------------------------------------------------------------------------------------------
22
23     /**
24      * Returns a new instance of {@link OmniPartialViewContext} which wraps the original partial view context.
25      */
26     @Override
27     public PartialViewContext getPartialViewContext(FacesContext context) {
28         return new CustomPartialViewContext(wrapped.getPartialViewContext(context));
29     }
30
31     /**
32      * Returns the wrapped factory.
33      */
34     @Override
35     public PartialViewContextFactory getWrapped() {
36         return wrapped;
37     }
38
39 }

该类重写还需要一个PartialViewContext ,此处没有直接继承PartialViewContext ,而是继承了PartialViewContext 的子类PartialViewContextWrapper,并重写了里面的方法:

  1 /**
  2  * <p>
  3  * This OmniFaces partial view context extends and improves the standard partial view context as follows:
  4  * <ul>
  5  * <li>Support for executing callback scripts by {@link PartialResponseWriter#startEval()}.</li>
  6  * <li>Support for adding arguments to an ajax response.</li>
  7  * <li>Any XML tags which Mojarra and MyFaces has left open after an exception in rendering of an already committed
  8  * ajax response, will now be properly closed. This prevents errors about malformed XML.</li>
  9  * <li>Fixes the no-feedback problem when a {@link ViewExpiredException} occurs during an ajax request on a page which
 10  * is restricted by <code>web.xml</code> <code>&lt;security-constraint&gt;</code>. The enduser will now properly be
 11  * redirected to the login page instead of retrieving an ajax response with only a changed view state (and effectively
 12  * thus no visual feedback at all).</li>
 13  * </ul>
 14  * You can use the {@link Ajax} utility class to easily add callback scripts and arguments.
 15  * <p>
 16  * This partial view context is already registered by OmniFaces‘ own <code>faces-config.xml</code> and thus gets
 17  * auto-initialized when the OmniFaces JAR is bundled in a web application, so end-users do not need to register this
 18  * partial view context explicitly themselves.
 19  *
 20  * @author Bauke Scholtz
 21  * @since 1.2
 22  * @see OmniPartialViewContextFactory
 23  */
 24 public class CustomPartialViewContext extends PartialViewContextWrapper {
 25
 26     // Constants ------------------------------------------------------------------------------------------------------
 27
 28     private static final String AJAX_DATA = "var Faces=Faces||{};Faces.Ajax={data:%s};";
 29     private static final String ERROR_NO_OMNI_PVC = "There is no current CustomPartialViewContext instance.";
 30
 31     // Variables ------------------------------------------------------------------------------------------------------
 32
 33     private PartialViewContext wrapped;
 34     private Map<String, Object> arguments;
 35     private List<String> callbackScripts;
 36     private CustomPartialResponseWriter writer;
 37
 38     // Constructors ---------------------------------------------------------------------------------------------------
 39
 40     /**
 41      * Construct a new OmniFaces partial view context around the given wrapped partial view context.
 42      * @param wrapped The wrapped partial view context.
 43      */
 44     public CustomPartialViewContext(PartialViewContext wrapped) {
 45         this.wrapped = wrapped;
 46         setCurrentInstance(this);
 47     }
 48
 49     // Actions --------------------------------------------------------------------------------------------------------
 50
 51     @Override
 52     public PartialResponseWriter getPartialResponseWriter() {
 53         if (writer == null) {
 54             writer = new CustomPartialResponseWriter(this, super.getPartialResponseWriter());
 55         }
 56
 57         return writer;
 58     }
 59
 60     @Override // Necessary because this is missing in PartialViewContextWrapper (will be fixed in JSF 2.2).
 61     public void setPartialRequest(boolean partialRequest) {
 62         getWrapped().setPartialRequest(partialRequest);
 63     }
 64
 65     @Override
 66     public PartialViewContext getWrapped() {
 67         return wrapped;
 68     }
 69
 70     /**
 71      * Add an argument to the partial response. This is as JSON object available by <code>OmniFaces.Ajax.data</code>.
 72      * For supported argument value types, read {@link Json#encode(Object)}. If a given argument type is not supported,
 73      * then an {@link IllegalArgumentException} will be thrown during end of render response.
 74      * @param name The argument name.
 75      * @param value The argument value.
 76      */
 77     public void addArgument(String name, Object value) {
 78         if (arguments == null) {
 79             arguments = new HashMap<>();
 80         }
 81
 82         arguments.put(name, value);
 83     }
 84
 85     /**
 86      * Add a callback script to the partial response. This script will be executed once the partial response is
 87      * successfully retrieved at the client side.
 88      * @param callbackScript The callback script to be added to the partial response.
 89      */
 90     public void addCallbackScript(String callbackScript) {
 91         if (callbackScripts == null) {
 92             callbackScripts = new ArrayList<>();
 93         }
 94
 95         callbackScripts.add(callbackScript);
 96     }
 97
 98     /**
 99      * Reset the partial response. This clears any JavaScript arguments and callbacks set any data written to the
100      * {@link PartialResponseWriter}.
101      * @see FullAjaxExceptionHandler
102      */
103     public void resetPartialResponse() {
104         if (writer != null) {
105             writer.reset();
106         }
107
108         arguments = null;
109         callbackScripts = null;
110     }
111
112     /**
113      * Close the partial response. If the writer is still in update phase, then end the update and the document. This
114      * fixes the Mojarra problem of incomplete ajax responses caused by exceptions during ajax render response.
115      * @see FullAjaxExceptionHandler
116      */
117     public void closePartialResponse() {
118         if (writer != null && writer.updating) {
119             try {
120                 writer.endUpdate();
121                 writer.endDocument();
122             }
123             catch (IOException e) {
124                 throw new FacesException(e);
125             }
126         }
127     }
128
129     // Static ---------------------------------------------------------------------------------------------------------
130
131     /**
132      * Returns the current instance of the OmniFaces partial view context.
133      * @return The current instance of the OmniFaces partial view context.
134      * @throws IllegalStateException When there is no current instance of the OmniFaces partial view context. That can
135      * happen when the {@link OmniPartialViewContextFactory} is not properly registered, or when there‘s another
136      * {@link PartialViewContext} implementation which doesn‘t properly delegate through the wrapped instance.
137      */
138     public static CustomPartialViewContext getCurrentInstance() {
139         return getCurrentInstance(getContext());
140     }
141
142     /**
143      * Returns the current instance of the OmniFaces partial view context from the given faces context.
144      * @param context The faces context to obtain the current instance of the OmniFaces partial view context from.
145      * @return The current instance of the OmniFaces partial view context from the given faces context.
146      * @throws IllegalStateException When there is no current instance of the OmniFaces partial view context. That can
147      * happen when the {@link OmniPartialViewContextFactory} is not properly registered, or when there‘s another
148      * {@link PartialViewContext} implementation which doesn‘t properly delegate through the wrapped instance.
149      */
150     public static CustomPartialViewContext getCurrentInstance(FacesContext context) {
151         CustomPartialViewContext instance = getContextAttribute(context, CustomPartialViewContext.class.getName());
152
153         if (instance != null) {
154             return instance;
155         }
156
157         // Not found. Well, maybe the context attribute map was cleared for some reason. Get it once again.
158         instance = unwrap(context.getPartialViewContext());
159
160         if (instance != null) {
161             setCurrentInstance(instance);
162             return instance;
163         }
164
165         // Still not found. Well, maybe RichFaces is installed which doesn‘t use PartialViewContextWrapper.
166         if (Hacks.isRichFacesInstalled()) {
167             PartialViewContext pvc = Hacks.getRichFacesWrappedPartialViewContext();
168
169             if (pvc != null) {
170                 instance = unwrap(pvc);
171
172                 if (instance != null) {
173                     setCurrentInstance(instance);
174                     return instance;
175                 }
176             }
177         }
178
179         // Still not found. Well, it‘s end of story.
180         throw new IllegalStateException(ERROR_NO_OMNI_PVC);
181     }
182
183     private static void setCurrentInstance(CustomPartialViewContext instance) {
184         setContextAttribute(CustomPartialViewContext.class.getName(), instance);
185     }
186
187     private static CustomPartialViewContext unwrap(PartialViewContext context) {
188         PartialViewContext unwrappedContext = context;
189
190         while (!(unwrappedContext instanceof CustomPartialViewContext) && unwrappedContext instanceof PartialViewContextWrapper) {
191             unwrappedContext = ((PartialViewContextWrapper) unwrappedContext).getWrapped();
192         }
193
194         if (unwrappedContext instanceof CustomPartialViewContext) {
195             return (CustomPartialViewContext) unwrappedContext;
196         }
197         else {
198             return null;
199         }
200     }
201
202     // Nested classes -------------------------------------------------------------------------------------------------
203
204     /**
205      * This OmniFaces partial response writer adds support for passing arguments to JavaScript context, executing
206      * oncomplete callback scripts, resetting the ajax response (specifically for {@link FullAjaxExceptionHandler}) and
207      * fixing incomlete XML response in case of exceptions.
208      * @author Bauke Scholtz
209      */
210     private static class CustomPartialResponseWriter extends PartialResponseWriter {
211
212         // Variables --------------------------------------------------------------------------------------------------
213
214         private CustomPartialViewContext context;
215         private PartialResponseWriter wrapped;
216         private boolean updating;
217
218         // Constructors -----------------------------------------------------------------------------------------------
219
220         public CustomPartialResponseWriter(CustomPartialViewContext context, PartialResponseWriter wrapped) {
221             super(wrapped);
222             this.wrapped = wrapped; // We can‘t rely on getWrapped() due to MyFaces broken PartialResponseWriter.
223             this.context = context;
224         }
225
226         // Overridden actions -----------------------------------------------------------------------------------------
227
228         /**
229          * An override which checks if the web.xml security constraint has been triggered during this ajax request
230          * (which can happen when the session has been timed out) and if so, then perform a redirect to the originally
231          * requested page. Otherwise the enduser ends up with an ajax response containing only the new view state
232          * without any form of visual feedback.
233          */
234         @Override
235         public void startDocument() throws IOException {
236             wrapped.startDocument();
237             String loginURL = WebXml.INSTANCE.getFormLoginPage();
238
239             if (loginURL != null) {
240                 FacesContext facesContext = FacesContext.getCurrentInstance();
241                 String loginViewId = normalizeViewId(facesContext, loginURL);
242
243                 if (loginViewId.equals(getViewId(facesContext))) {
244                     String originalURL = getRequestAttribute(facesContext, "javax.servlet.forward.request_uri");
245
246                     if (originalURL != null) {
247                         redirect(originalURL);
248                     }
249                 }
250             }
251         }
252
253         /**
254          * An override which remembers if we‘re updating or not.
255          * @see #endDocument()
256          * @see #reset()
257          */
258         @Override
259         public void startUpdate(String targetId) throws IOException {
260             updating = true;
261             wrapped.startUpdate(targetId);
262         }
263
264         /**
265          * An override which remembers if we‘re updating or not.
266          * @see #endDocument()
267          * @see #reset()
268          */
269         @Override
270         public void endUpdate() throws IOException {
271             updating = false;
272             wrapped.endUpdate();
273         }
274
275         /**
276          * An override which writes all {@link OmniPartialViewContext#arguments} as JSON to the extension and all
277          * {@link OmniPartialViewContext#callbackScripts} to the eval. It also checks if we‘re still updating, which
278          * may occur when MyFaces is used and an exception was thrown during rendering the partial response, and then
279          * gently closes the partial response which MyFaces has left open.
280          */
281         @Override
282         public void endDocument() throws IOException {
283             if (updating) {
284                 // If endDocument() method is entered with updating=true, then it means that MyFaces is used and that
285                 // an exception was been thrown during ajax render response. The following calls will gently close the
286                 // partial response which MyFaces has left open.
287                 // Mojarra never enters endDocument() method with updating=true, this is handled in reset() method.
288                 endCDATA();
289                 endUpdate();
290             }
291             else {
292                 if (context.arguments != null) {
293                     startEval();
294                     write(String.format(AJAX_DATA, Json.encode(context.arguments)));
295                     endEval();
296                 }
297
298                 if (context.callbackScripts != null) {
299                     for (String callbackScript : context.callbackScripts) {
300                         startEval();
301                         write(callbackScript);
302                         endEval();
303                     }
304                 }
305             }
306
307             wrapped.endDocument();
308         }
309
310         // Custom actions ---------------------------------------------------------------------------------------------
311
312         /**
313          * Reset the partial response writer. It checks if we‘re still updating, which may occur when Mojarra is used
314          * and an exception was thrown during rendering the partial response, and then gently closes the partial
315          * response which Mojarra has left open. This would clear the internal state of the wrapped partial response
316          * writer and thus make it ready for reuse without risking malformed XML.
317          */
318         public void reset() {
319             try {
320                 if (updating) {
321                     // If reset() method is entered with updating=true, then it means that Mojarra is used and that
322                     // an exception was been thrown during ajax render response. The following calls will gently close
323                     // the partial response which Mojarra has left open.
324                     // MyFaces never enters reset() method with updating=true, this is handled in endDocument() method.
325                     endCDATA();
326                     endUpdate();
327                     wrapped.endDocument();
328                 }
329             }
330             catch (IOException e) {
331                 throw new FacesException(e);
332             }
333             finally {
334                 responseReset();
335             }
336         }
337
338         // Delegate actions -------------------------------------------------------------------------------------------
339         // Due to MyFaces broken PartialResponseWriter, which doesn‘t delegate to getWrapped() method, but instead to
340         // the local variable wrapped, we can‘t use getWrapped() in our own PartialResponseWriter implementations.
341
342         @Override
343         public void startError(String errorName) throws IOException {
344             wrapped.startError(errorName);
345         }
346
347         @Override
348         public void startEval() throws IOException {
349             wrapped.startEval();
350         }
351
352         @Override
353         public void startExtension(Map<String, String> attributes) throws IOException {
354             wrapped.startExtension(attributes);
355         }
356
357         @Override
358         public void startInsertAfter(String targetId) throws IOException {
359             wrapped.startInsertAfter(targetId);
360         }
361
362         @Override
363         public void startInsertBefore(String targetId) throws IOException {
364             wrapped.startInsertBefore(targetId);
365         }
366
367         @Override
368         public void endError() throws IOException {
369             wrapped.endError();
370         }
371
372         @Override
373         public void endEval() throws IOException {
374             wrapped.endEval();
375         }
376
377         @Override
378         public void endExtension() throws IOException {
379             wrapped.endExtension();
380         }
381
382         @Override
383         public void endInsert() throws IOException {
384             wrapped.endInsert();
385         }
386
387         @Override
388         public void delete(String targetId) throws IOException {
389             wrapped.delete(targetId);
390         }
391
392         @Override
393         public void redirect(String url) throws IOException {
394             wrapped.redirect(url);
395         }
396
397         @Override
398         public void updateAttributes(String targetId, Map<String, String> attributes) throws IOException {
399             wrapped.updateAttributes(targetId, attributes);
400         }
401
402     }
403 }

可以看到其中定义了两个常量,一个警告说明,一个名为AJAX_DATA,里面写的是一段js的字符串。这个常量用在了 被重写的endDocument()方法里。这个方法主要做了两件事,第一是写入要传递的数据,并且以json格式打包,第二件事是包含了一个js方法。那么可以这样认为:该方法的作用是用一个js方法取得发送的数据。

  首先我们必须清楚,JSF使用f:ajax更新客户端的底层操作是怎样的。JSF更新数据是向页面发送了xml数据的,可以在firefox的 firebug下面的网络-XML面板下看到发送的xml数据,类似于以下的数据:

1 <partial-response id="j_id1">
2   <changes>
3     <update id="j_id1:javax.faces.ViewState:0">-4426271603414575392:-5845678956333562288</update>
4   </changes>
5 </partial-response>

里面包含了需要更新的组件和组件状态。

我把omnifaces的Ajax代码整理出来以后,根据官方例子的用法,写了一个小demo测试,其中页面form表单代码如下:

 1 <h:form prependId="false">
 2         <h:outputLabel value="#{test2.radom}" id="outLabel"/>
 3         <h:commandButton action="#{test2.callback}"  value="请求服务端js">
 4             <f:ajax/>
 5         </h:commandButton>
 6         <h:commandButton value="获取服务端数据到js">
 7             <f:ajax listener="#{test2.argument}"/>
 8         </h:commandButton>
 9
10         <h:commandButton value="showUser">
11             <f:ajax listener="#{test2.parseUser}"/>
12         </h:commandButton>
13 </h:form>

测试bean代码如下:

 1 @ManagedBean(name="test2")
 2 @ViewScoped
 3 public class Test2 implements Serializable {
 4
 5     private static final long serialVersionUID = 8686669721840131192L;
 6
 7     public void callback() {
 8         Ajax.oncomplete("alert(‘Hi, I am the oncomplete callback script!‘)");
 9     }
10
11     public void argument() {
12         Ajax.data("foo", "bar");
13         Ajax.data("first", "one", "second", "two");
14         Map<String, Object> data = new HashMap<>();
15         data.put("bool", true);
16         data.put("number", 1.2F);
17         data.put("date", new Date());
18         data.put("array", new Integer[] { 1, 2, 3, 4, 5 });
19         data.put("list", Arrays.asList("one", "two", "three"));
20         Ajax.data(data);
21         Ajax.oncomplete("showData()");
22     }
23
24     public void parseUser(){
25         Ajax.data("user", new User(1, "bigbang"));
26         Ajax.oncomplete("showUser()");
27     }
28
29 }

其中提供了三个页面响应的方法。当点击第一个button时,页面会弹出一个alert提示框。此时查看firefox下面的数据如下:

1 <partial-response id="j_id1">
2 <changes>
3 <update id="j_id1:javax.faces.ViewState:0">-4426271603414575392:-5845678956333562288</update>
4 <eval>alert(‘Hi, I am the oncomplete callback script!‘)</eval>
5 </changes>
6 </partial-response>

点击“获取数据到js”按钮,查看xml数据:

1 <partial-response id="j_id1">
2 <changes>
3 <update id="j_id1:javax.faces.ViewState:0">-3364647386979820288:-1391656100755852530</update>
4 <eval>var Faces=Faces||{};Faces.Ajax={data:{"second":"two","number":1.2,"list":["one","two","three"],"foo":"bar","bool":true,"date":"Fri, 17 Jul 2015 09:17:50 GMT","first":"one","array":[1,2,3,4,5]}};</eval>
5 <eval>showData()</eval>
6 </changes>
7 </partial-response>

点击“showuser”按钮,查看xml数据:

1 <partial-response id="j_id1">
2 <changes>
3 <update id="j_id1:javax.faces.ViewState:0">-3364647386979820288:-1391656100755852530</update>
4 <eval>var Faces=Faces||{};Faces.Ajax={data:{"user":{"id":1,"name":"bigbang"}}};</eval>
5 <eval>showUser()</eval>
6 </changes>
7 </partial-response>

可以看出刚才的那个endDocumnt方法和AJAX_DATA常量的用意了,实际是构造了一个js对象,然后传入一个js方法到客户端,客户端会自动调用这个js方法,根据对象取得json数据。那么客户端的js只需要这样写就可以了:

 1   <script>
 2     function showData() {
 3            var data = Faces.Ajax.data;
 4            $.each(data, function(key, value) {
 5                 console.log(key+"---"+JSON.stringify(value));
 6             });
 7       }
 8
 9       function showUser(){
10         var data = Faces.Ajax.data;
11         $.each(data, function(key,value){
12             var user = JSON.stringify(value);
13             var u = $.parseJSON(user);
14             console.log("userName----"+u.name);
15          }
16   </script>

控制台显示数据如下:

OK,大功告成了!其中的细节不用细究,无非就是掺杂了各种数据转换为json格式、数据的包装和写入。最后说明一点,omnifaces需要CDI的支持,必须导入CDI的jar包。

时间: 2024-12-16 06:55:50

JSF页面中的JS取得受管bean的数据(受管bean发送数据到页面)的相关文章

JSF页面中使用js函数回调后台bean方法并获取返回值的方法

由于primefaces在国内使用的并不是太多,因此,国内对jsf做系统.详细的介绍的资料很少,即使有一些资料,也仅仅是对国外资料的简单翻译或者是仅仅讲表面现象(皮毛而已),它们的语句甚至还是错误的,很可能会误导使用者. 相对来说,看国内的那些仅仅是翻译过来的文章或书籍不如直接看国外的官方文档或资料来的实在,在我讲述jsf页面中如何使用js调用后台bean方法之前,先给大家说几个国外的资料.在primefaces官方网站上,你可以搜索到几乎所有你需要的东西,primefaces官网为:http:

巧用开发者工具的控制台来调试页面中的js语句

因为要弄某网页的一个自动登陆工具,所以需要对此网页中的元素利用js进行选取和操作,复杂的js选取如果直接在头脑中想很容易出错,而且一旦出错也不好判断错误原因. 而浏览器带的开发者工具的控制台功能,就给我们提供了一个像在本地开发工具中调试程序一样便捷的功能. 比如要调试博客首页,鼠标右键选择页面中对应的元素,弹出的菜单选择审查元素: 假设我们要选取图中标题的a标签元素,它的id为homepage1_HomePageDays_DaysList_ctl00_DayList_TitleUrl_0,那么我

对于HTML页面中CSS, JS, HTML的加载与执行过程的简单分析

最近在研究HTML页面中JavaScript的执行顺序问题.在JavaScript中,定义一个方法或者函数有很多方式,最常见的有2中,function语句式与函数直接量方式. 对于function语句式,解释器会优先解释.即加载了这个js文件后,会扫描一下所有的js代码,然后把该优先执行的东西先执行了,然后再从上到下按顺序执行.所以,定义的代码可以在执行的代码后边.就跟C#中的方法定义一样.解释器已经记住了这个方法,知道在内存中的哪里,用的时候直接去取就行了. C#语言是,对象中的属性与方法具有

在页面中使用js

JavaScript:用来在页面编写特效的,和HTML\CSS一样当都是由浏览器解析 JavaScript语言 一.JS如何运行(JavaScript,jscript,VbScript,applet ... ) 二.输出 alert(什么类型都可以); document.write("字符串"); 三.如何在HTML文档中使用JS 1.使用<script></script>将JS语法嵌入到HTML中,可以使用多个,每一个都是有关联的 2.href="j

页面中引入js的几种方法

通常大家最为熟悉的是一下两种方法: 在页面中直接写入<script type="text/javascript">js代码</script>. 在页面中引入外部文件<script src="xx.js"></script>. 下面再介绍几种页面引入js的代码: 在js中引入外部js,通过document.wirite("scr"+"ipt src='xx.js'></scr&q

js中全局变量修改后的值不生效【jsp页面中各个js中内容的加载顺序】

一个老项目中,一个jsp文件中有很多个js文件, 现在要在页面上的一个地方判断一个状态,因为一直找不到原来是在哪里修改的那个状态,所以决定不找了,而是在比较靠前引入的一个js中定义一个全局变量,然后在这个js的 $(function(){}} 方法中通过一个ajax向后台获取正确的状态,然后在所有的js都加载完之后根据全局变量的值的状态来修改页面上的逻辑. 但是发现,全局变量被一个外部js修改赋值后,我在jsp页面的最下面居然取不到修改过的值. 请教同事才发现原来原因是 任何一个js文件中的 $

webview页面中注入js的时机深入

webview中有WebChromeClient类来完成回调,在整个页面的加载过程中,在哪个阶段进行js注入呢? 经过深入实践后, 如果在OnPageStarted回调时注入的话,有可能注入不成功,这样导致页面脚本中接口不可用. 如果在onpagefinish()中完成.由于页面document.ready的初始化回调而导致等待时间过长. 想把这个过程提前,在页面window对象创建时加载呢,webview目前又没有这样的回调. 这样的话想一个折中的处理方案,onProgressChanged在

怎样确保页面中的js代码一定是在DOM结构生成之后再调用

有这样一类问题, 如下所示, 就是在dom结构没有生成时就在js代码中调用了, 此时就会报错: <head> <script> console.log(document.body.nodeName); </script> </head> <body> </body> 上图所示的代码表明, 如果js代码在页面DOM没有解析出来时, document无法获取body元素, 这样就会造成报错. 解决方法有下面两种: 1. 将操作dom的代码

微信小程序使用wxs在页面中调用js函数,颜色值格式转换 rgb和十六进制的转换

<wxs module="filter"> var filter = { numberToFix: function (hex) { // 16进制颜色值的正则 // var reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/; var reg = getRegExp('^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$','g'); console.log(reg); console.log('结束'); // 把颜色值