单页WEB应用(二),Shell核心模块,模块组装器

本文解析了单页应用(SPA)的核心模块Shell的设计与实现,包括模块配置、状态管理和jQuery元素缓存等方面,阐述了如何通过配置和初始化过程组装子模块。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心模块 Shell

该模块是整个单页应用的核心模块,也可以说是顶级模块,用来组装和管理其他子模块的模块,其实该书中的所有模块都有模版,作者将其放到了附录里面,东西也不多主要就这几块:

  1. 模块配置
  2. jquery 缓存组件数据
  3. 模块初始化
  4. 和一些其他的功能方法等

例如:Shell模块就包含以下内容

模块配置
  • 模块基本配置对象:configMap

    例如:shell 模块的基本配置

    var configMap = {
    
        /*
            这个配置,是每个模块都需要的配置,主要针对模块的页面
    
            字符串形式,保存了模块的结构代码,通过jQuery.html方法
    
            添加到其父级元素下(即包含该模块的容器里面,相对shell模块,该容器即 id='spa' 的 div)
    
            比如下面的内容即shell模块所包含的组件
        */
        main_html: ''
            + '<div id="spa">'
                + '<div class="spa-shell-head">'
                    + '<div class="spa-shell-head-logo"></div>'
                    + '<div class="spa-shell-head-acct"></div>'
                    + '<div class="spa-shell-head-search"></div>'
                + '</div>'
                + '<div class="spa-shell-main">'
                    + '<div class="spa-shell-main-nav"></div>'
                    + '<div class="spa-shell-main-content"></div>'
                + '</div>'
                + '<div class="spa-shell-foot"></div>'
                + '<div class="spa-shell-modal"></div>'
            + '</div>'
    },
    
    stateMap = {},
    
    jqueryMap = {}
    
    
  • 模块状态配置:stateMap

    该对象保存了模块内几乎所有可变数据的变化及状态值,从而统一管理模块数据,和数据的变化,说白了 其实就是跟模块相关的变量,状态值的一个容器。

    下面是 shell 模块的状态配置

    var stateMap    = { 
        $container          : null,
        anchor_map          : {}
    }
    
    /*
        这里东西不多,主要保存了两个属性
    
        $container: 几乎每个模块都存在,即包含该模块的组件
    
    */

    再看后面一个子模块:chat 聊天模块的状态值

    var stateMap = {
        $container: null,
    
        position_type       : 'closed',
        px_per_em           : 0,
        slider_hidden_px    : 0,
        slider_closed_px    : 0,
        slider_opened_px    : 0
    }
    
    /*
        这个模块的东西就稍微多点,包含
    
        聊天模块位置类型:'closed', 'opened', 'hidden',说明这个值会在这三个之间发生变化,并且由 stateMap 容器来保管维护
    
        以及下面的其他属性或状态值等等
    */
  • jQuery 容器: jqueryMap

    第三个就是 jQuery 的容器了,刚接触时还不太明白用处,现在大概明白了,其实就是缓存的作用,在这里会将 jQuery 所用的的数据,元素等先缓存起来,不至于用的时候再去重新读取元素,这可能会牺牲点开始的加载速度,不过这点影响估计可以忽略不记了(毕竟一个模块的元素还是有限的,也不会太多,并且针对单个元素的获取速度应该还是很快的),这对后面通过 jQuery 去访问元素将是一大便捷和快速,同时也能很明了的从这里看出模块大概所涉及的元素,或其他一些信息。

    var jqueryMap = {};

    由于涉及到DOM元素对象,加上模块又是动态加载到DOM中的,所以针对这个容器,有个对应的设置函数:setJqueryMap,一般会在模块调用 $.html 之后调用,去初始化该容器

    shell 模块

    setJqueryMap = function () {
    
        var $container = stateMap.$container;
    
        jqueryMap = {
            $container: $container
        };  
    };

    chat 子模块

    setJqueryMap = function () {
    
        var 
            $append_target = stateMap.$append_target,
            $slider = $append_target.find( '.spa-chat' );
    
        // chat模块相对来说保存的元素对象比较全点,这里就缓存了聊天
        // 模块的所有元素,而不至于在后续使用过程中再去获取,这种方式更加高效,相对后续的操作会更快点
    
        jqueryMap = {
            $slider : $slider,
            $head 	: $slider.find( '.spa-chat-head' ),
            $toggle	: $slider.find( '.spa-chat-head-toggle' ),
            $title 	: $slider.find( '.spa-chat-head-title' ),
            $sizer 	: $slider.find( '.spa-chat-sizer' ),
            $msgs 	: $slider.find( '.spa-chat-msgs' ),
            $box 	: $slider.find( '.spa-chat-box' ),
            $input 	: $slider.find( '.spa-chat-box input[type=text]' ),
        };  
    };
    
shell 模块函数,及模块处理控制

这个模块,主要起到组装子模块作用,实际上shell模块本身是不需要多少控制代码,最多会包含一些全局性的控制或辅助部分,比如:URL的 Hash 变化和控制,作者使用了个锚控制 jquery 插件:uriAnchor,大概的功能和代码了解了点,有些地方还是不太清晰,后面会针对这个插件研究下

其实大概的原理不是很复杂,主要涉及的其实就是,针对每个模块去维护自己的状态值,然后 uriAnchor 插件实时的去更新状态值,其中有个比较容易忽略的地方,也是其中一个核心的地方,就是 anchor_schema_map 这个锚映射表中的值,必须是 true 后面才会起到作用,因为这个纠结了一整天,坑死了。

具体的细节还不是非常清晰,这篇之后会去研究下,然后自己实现下,这个插件针对单页应用,或者需要自己手动实现浏览器上的‘前进’,‘后退’,‘刷新’等功能还是很有帮助的。

  • 组装子模块

    比如:当下实现的 chat 聊天模块,先配置后初始化,配置的主要有chat 模块点击指定地方之后触发点击事件,然后调用 set_chat_anchor 去改变当前 URL 的 hash 值,然后核心shell 模块会监控 urlhash 值的变化事件,做出相应的行为

    // spa.chat.js
    
    // chat_model, people_model 属于模块私有的数据模型
    
    spa.chat.configModule({
        set_chat_anchor : setChatAnchor,
        chat_model      : spa.model.chat,
        people_model    : spa.model.people
    });
    
    // 执行的初始化里面,会将当前模块的 html 代码追加到参数中的容器后面,加上
    // spa.chat.css 模块的样式,便能完整在容器中显示出来
    spa.chat.initModule( jqueryMap.$container );

总结

  • 模版

    该书中的单页应用模版,不管是核心总管shell 或者 子模块都能套用该模版,主要内容就文头说的三大块,数据块,控制逻辑,和初始化,总体布局还是比较清晰的。

    而主要实现方式,其实还是立即执行匿名函数方式:

    // spa.module.template.js
    
    
    spa.module = (function () {
    
        var 
            configMap = {
    
                main_html: '' 
                    + '<div>'
                    + 'Module Html'
                    + '</div>',
    
                settable_map: { color_name: true },
    
                color_name: 'blue'
            },
    
            stateMap = {
                $container: null
            },
    
            jqueryMap = {},
    
            setJqueryMap, configModule, initModule;
    
    
        /* ----------------------- BEGIN UTILITY METHODS ----------------------- */
    
    
        setJqueryMap = function () {
    
            var $container = stateMap.$container;
    
            jqueryMap = {
                $container: $container
            };  
        };
    
        /* ----------------------- END UTILITY METHODS ----------------------- */
    
    
        /* ----------------------- BEGIN DOM METHODS ----------------------- */
        /* ----------------------- END DOM METHODS ----------------------- */
    
    
        /* ----------------------- BEGIN EVENT METHODS ----------------------- */
        /* ----------------------- END EVENT METHODS ----------------------- */
    
    
        /* ----------------------- BEGIN PUBLIC METHODS ----------------------- */
    
    
        /**
         * 配置允许访问的键值
         * 
         * @param  {Object} input_map 允许设置的属性的键值对
         *
         * configMap.settable_map 中保存了允许设置的属性
         * 
         * @return {[type]}           [description]
         */
        configModule = function ( input_map ) {
    
            spa.util.setConfigMap({
                input_map       : input_map,
                settable_map    : configMap.settable_map,
                config_map      : configMap
            });
    
            return true;
        };
    
    
        initModule = function ( $container ) {
    
            stateMap.$container = $container;
    
            setJqueryMap();
    
            return true;    
        };
    
        /* ----------------------- END PUBLIC METHODS ----------------------- */
    
        return {
            configModule    : configModule,
            initModule      : initModule
        };
    
    });
    
    
  • 心得

    目前学习完第四章,代码也基本手敲了一遍,经过这日志记录,思路也重新缕了一遍,这书的模块的实现对于我这种初学者来学还是值得学习的,遇到的问题和不解最多的还是那个 uriAnchor 插件的实现,虽然原理不是很复杂,还是需要去琢磨下,争取彻底明白原理,自己能实现。

    该书目前阅读进度来说值得学习借鉴的地方

    • 数据的统一性:通过一个统一的配置容器来管理每个模块自己的数据;
    • 缓存的重要性:通过缓存来减少操作过程中重复获取 DOM 元素;
    • 模块依赖性:尽量减少模块之间的依赖程度;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若叶岂知秋vip

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值