The following is the interface similar to the main interface of a product we are developing. The front-end display adopts flex development, and the back-end system is based on the Java SOA framework. The navigation bar is on the left side of the interface, and the content area is on the right side (of course there are other topics, which are ignored here ). The content area is generally composed of multiple UI parts. Each part uses an asynchronous mechanism to obtain data from the backend. In addition, it will receive notification messages from the backend. The entire interface is very compatible with Microsoft's cab philosophy. However, Flex is not built with a cab, but a piece of content can be defined using Microsoft user controls. Ui parts in the interface content area may be reused.
In the design process, I want to use the interface combination idea for design. The advantages of this idea include: 1) the interface is divided into different components, each of which implements a function, more in line with the SRP principle; 2) when implementing each UI part, you only need to focus on the implementation of a piece of content in the complex interface, which is relatively simple; 3) easy to implement reuse; disadvantages: 1) each interface consists of multiple UI parts, which need to maintain the connection between UI parts. 2) it is not easy for beginners to understand the implementation of the interface.
In view of the many advantages of Microsoft's interface combination, I decided to introduce the idea to flex and implement a composition SDK Based On Flex by myself. During the SDK implementation process, I referred to cab & scsf and prism.
Considering the functions required by the software, the SDK supports the following functions:
1. UI part lifecycle management. When each UI part is displayed, You need to obtain data from the backend and listen to the data update message. When you click Tab 2 on the page, Tab 1 is hidden and the listening message is stopped, tab 2 is displayed. In my opinion, each UI part has the activated, deactivated, and closed lifecycle States. When it is in the activated state, the UI part displays the required data. When it is in the deactivated state, the UI part is hidden and the updated data is stopped. When it is in the closed state, the UI part is closed and the updated data is stopped, and it is destroyed. The purpose of the lifecycle management function is to achieve data update driven by lifecycle changes, that is, each component data update is determined by its own lifecycle status, it does not need to be controlled by the parent node to achieve greater granularity reuse.
2. UI part combination and dynamic injection. This function allows you to define each UI part in the view container class. In this mode, once the container is displayed, all the UI parts are displayed; or some of the UI parts are dynamically injected and rendered at runtime. when the container is rendered, a specific UI part is injected as needed.
3. Support for Master-Details UI part. The Master-Details UI part is a special UI part. When the data of the master UI part changes, the details UI part also needs to be updated, and. net master-Details View is the same.
4. Use the hook mechanism to implement ~ When using the three functions, you can try to be compatible with standard controls without creating custom controls or just creating very simple custom controls. The hook mechanism works as follows: a) each function is implemented by a hook; B) for example, lifecyclehook. When a leaf node component is displayed, hidden, or closed, the hook must maintain its status. For a container node, it must maintain its own status and the status of sub-controls, such as vbox containers. When vbox is displayed, the status is activated and the status of all its first-level subnodes is also activated. For the tabnavigator container, when it is displayed, its status is activated and the status of the Selected tab is also activated, the status of other tabs is deactivated; c) the hook creation process is a recursive listening interface root node onchildadded/removed event; d) the SDK provides the hook registry and hook manager, the hook registry defines the hooks corresponding to each type of components, while the hook manager defines the hook instances corresponding to each control.
5. Based on this SDK, the design of each view consists of the workspace and UI part. The workspace uses the flex standard container control to define the interface layout. The UI part is the implementation of each part of the interface, it encapsulates lifecycle-driven data updates.
Code The design is relatively simple, and its structure is as follows:
Componenttreehook is the core class of the entire hook mechanism. It listens to the onchildadded/removed controls of the root node recursively. When a subnode is added, the entire control tree is mounted recursively. The mounting process code is as follows: Code
1 /* *
2 * Create the hooks for current component tree and listen the child_add/child_remove
3 * Events of each component.
4 *
5 * @ Param comp the root component of the component tree.
6 *
7 */
8 Override public Function Hook (COMP: uicomponent ): Void
9 {
10 If ( ! Ishooked)
11 {
12 Super. Hook (COMP );
13 Hookcomponenttree (component );
14 }
15 }
16
17 Private Function Hookcomponenttree (COMP: uicomponent ): Void
18 {
19 Docomponenttreehooking (COMP, True , Hookcomponentnode );
20 }
21
22 /* *
23 * Do the hooking for a component tree.
24 * @ Param comp the root component.
25 * @ Param hookcomponentfunc the actual hook function.
26 *
27 */
28 Private Function Docomponenttreehooking (COMP: uicomponent, hooked: Boolean, hookcomponentfunc: function ): Void
29 {
30 If ( ! Comp)
31 {
32 Return ;
33 }
34
35 // Hook the node from top to bottom.
36 VaR Queue: Array = [Comp];
37 VaR Tempcomp: uicomponent = Null ;
38 VaR Tempcontainer: Container = Null ;
39 VaR Tempcontainerchildren: array;
40 While (Queue. Length > 0 )
41 {
42 // Get a component from queue.
43 Tempcomp = Queue. Shift () as uicomponent;
44 If ( ! Tempcomp)
45 {
46 Continue ;
47 }
48
49 // Do the hook for this component.
50 Hookcomponentfunc (tempcomp );
51
52 // Get the children of current component and push them to queue.
53 Tempcontainer = Tempcomp as container;
54 // Smartpart here is treast as a component.
55 If (Tempcontainer && ! (Tempcontainer is ismartpart ))
56 {
57 If (Hooked)
58 {
59 Tempcontainer. addeventlistener (childexistencechangedevent. child_add, onchildadded, False , Compositioneventpriority. create_hook );
60 Tempcontainer. addeventlistener (childexistencechangedevent. child_remove, onchildremoved, False , Compositioneventpriority. destory_hook );
61 }
62 Else
63 {
64 Tempcontainer. removeeventlistener (childexistencechangedevent. child_add, onchildadded );
65 Tempcontainer. removeeventlistener (childexistencechangedevent. child_remove, onchildremoved );
66 }
67 Tempcontainerchildren = Tempcontainer. getchildren ();
68 For Each ( VaR Child: uicomponent In Tempcontainerchildren)
69 {
70 Queue. Push (child );
71 }
72 }
73 }
74 }
The attachment is the test file of the SDK, including the UI test and unit test. Test File