SoFunction
Updated on 2025-03-01

xmlplus component design series routing (ViewStack) (7)

On the browser side, the understanding of routing is generally to complete the page switching based on different URLs. On the server side, it is to request feedback to the relevant page according to different URLs. In this chapter, we have a broad definition of component routing: the component object presents different child pages according to the different commands received. Here we will introduce a component related to routing, namely the ViewStack.

Preliminary view stack

The component is indocumentThe last chapter of the 》 section "Delayed instantiation》 has appeared. Some details will be interpreted here. The source code of this component is given again below.

ViewStack: { 
 xml: "<div id='viewstack'/>",
 fun: function (sys, items, opts) {
  var args, children = (),
   table = ("hide").hash(),
   ptr = table[] || children[0];
  if (ptr) ptr = ("show").show();
  ("switch", function ( e, to ) {
   table = ().hash();
   if ( !table[to] || table[to] == ptr ) return;
   ();
   args = [].(arguments).slice(2);
   ("hide", [to+''].concat(args)).hide();
   ptr = table[to].trigger("show", [ptr+''].concat(args)).show();
  });
  return ({}, "selected", { get: function() {return ptr;}});
 }
}

From the perspective of a static interface, this component allows the static parameter index, which is the name of a child component object of the component ViewStack component, which indicates which child component will be rendered first. Please see the example below.

Example1: {
 xml: `<ViewStack index='bar'>
    <button id='foo'>foo</button>
    <button id='bar'>bar</button>
   </ViewStack>`
}

In this example, ViewStack contains an attribute index with a value of bar, indicating that when the component is instantiated, the component object bar will be rendered first. By default, the first child of the component will be used as the initial display object. From the dynamic interface, the function item of this component exports a read-only property named selected, which is used to indicate the currently displayed child component object.

Switch target component object through events

For switching between child component objects, the component's function items do not export the relevant interface, but instead complete the switching by receiving a switch event. Please see the example below.

Example2: {
 xml: "<ViewStack id='viewstack'>\
    <button id='foo'>foo</button>\
    <button id='bar'>bar</button>\
   </ViewStack>"
 fun: function (sys, items, opts) {
  ("click", "*", function(e) {
   var to = this + '' == "foo" ? "bar" : "foo",
    data = "hello, world";
   ("switch", [to, data]);
  });
  ("show", function (e, prev, data) {
   ("previous page is " + prev, "from data is " + data);
  });
  ("hide", function (e, prev, data) {
   ("previous page is " + prev, "from data is " + data);
  });
 }
}

For this example, when the user clicks on the text, the text switches between foo and bar, that is, between two pages, and the switching is performed by dispatching switch events by the corresponding child object. In addition, when the component ViewStack switches the page, it will also distribute event show to the page displayed this time and hide to the page hidden this time. The relevant pages can choose whether to listen to or not according to needs. And in the listening function, you can know the previous display page ID and the transmitted related data.

Dynamically add and remove child objects

Component ViewStack supports dynamic addition and removal of child component objects, see an example below.

Example3: {
 xml: "<ViewStack id='viewstack'>\
    <button id='foo'>foo</button>\
   </ViewStack>"
 fun: function (sys, items, opts) {
  var xml = "<button id='bar'>bar</button>";
  (xml).trigger("switch", "bar");
 }
}

In this example, a child component is dynamically added to the function item, and the currently displayed view is switched to the newly added view by dispatching the event switch.

Optimized configuration

Component ViewStack is generally used with the component's delay instantiation function. For some more complex components, this helps to speed up the display of the application's initial page. Here is a simple demonstration.

Example4: {
 xml: `<ViewStack>
    <button id='foo'>foo</button>
    <button id='bar'>bar</button>
    <button id='alice'>alice</button>
   </ViewStack>`
 map: { defer: "bar alice" }
}

In this example, the ViewStack child contains three subcomponents, where the component objects bar and alice are set to require delayed instantiation, and they only start to instantiate when the show function of these two component objects is called.

Use with HTML5 History API

Here we look at how to use the component ViewStack with the HTML5 History API. Here is a simple example.

Example5: {
 xml: `<ViewStack id='example'>
    <button id='foo'>foo</button>
    <button id='bar'>bar</button>
    <button id='alice'>alice</button>
   </ViewStack>`,
 fun: function (sys, items, opts) {
  ("show", "button", function (e, prev) {
   ({name: this + ""}, null, "/" + this);
  });
  ("popstate", function(e) {
   ("switch", );
  });
 }
}

The key point of this example is that when the child page of the view stack component object changes, the function pushState is recorded; in addition, it is necessary to listen to the popstate event of the browser. When the user clicks the "Forward" and "Back" buttons, the corresponding page switch is completed. This technology is very suitable for completing refresh-free jumps in a single-page application, which can bring users a very good experience.

This series of articles is based on the xmlplus framework. If you don't know much about xmlplus, you can access it. Here are detailed introductory documentation for reference.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.