`

分享自己的Javascript交互模板

阅读更多

  在两年的工作中,经常会开发新的Web页面交互,或维护已存在的Web页面交互程序:javascript。由于 Javascript 是弱类型语言,且语言本身的约束性不是很强。Coding时如果没有统一的约束或规范,将会造成 .js 文件排版混乱不堪很难维护。

  现如今jQuery已经成为Web页面交互中不可缺少的组成部分,下面分享一套我在工作中累计的(个人认为)还不错的 .js 文件模板。

  

  • 解决通过$.load(或 $.html 等其他工具)加载的页面中包含 .js 文件时, 无法在部分浏览器定位并调试的问题。

 

// 调试开关, 页面初始化有效
FunctionFn.debug = true;

// 打印 .js 文件名
FunctionFn.debug && window.console && console.log("fileName.js");

 

 

 

  • 构建 Javascript 程序统一入口(jQuery入口)

 

// 页面加载完成后, 
// 在 onload 事件中注册交互事件和初始化页面数据
$(function() {

    // 将唯一实例绑定到函数(类)自身为了方便实时获取运算数据
    TestFn.instance = new TestFn();
    TestFn.instance.initEvents().initData();
});

 

 

  • 约定交互程序统一对外函数(initEvents 和 initData)

 

// 交互主体函数
function TestFn() {

    // 由于 this 会跟随上下文环境不同而变化
    // 在此记录交互实例对象, 以便于在需要时不必非常麻烦的通过 arguments.callee.caller 等方式获取上下文环境
    var $thisObj = this;

    // 交互主体所能控制的最顶层容器控件
    // 在后续查找控件时, 应从 baseCtnr 中开始查找: baseCtnr.find($ctrlSelector);
    // 而不是索引全局: $($ctrlSelector);
    // Base Container
    var baseCtnr = $(".current-base-container");

    // 1. 没有通过 new 关键字获取对象时, 返回执行环境对象
    // 2. 使用 new 关键字获取对象时, 返回 TestFn 的实例对象
    // 无论通过何种方式获取对象, 都可以访问绑定到 $thisObj 的函数和数据
    // 所以在此返回 this 是很有必要的
    return this;
}

 

 

  • 约定常量值集合(FINAL_VALUE)

 

// 用于保存运算过程中不能被变更的值, 实现时应使用 getter 函数方式. 如:
// var finalPageSize = FINAL_VALUE.VALUES.getFinalPageSize();

// 而不是直接定义数据属性: FINAL_VALUE.VALUES.FINAL_PAGE_SIZE = 10; 
// 这种方式很容易被无意识的修改

// 常量值字典对象
var FINAL_VALUE = {
    KEYS: {
        CONFIG_KEYS: {
            _summary: "本地配置字典"
        },
        SELECTORS: {
            _summary: "jQuery选择器字典"
        },
        ATTRIBUTES: {
            _summary: "控件属性字典"
        },
        _summary: "关键字字典 "
    },
    VALUES: {
        _summary: "常量值字典"
    },
    _summary: "常量值字典. 使用getter实现, 如: getFinalPageSize"
};

 

 

  • 约定数据对象(data)

 

// 数据集合
// 访问数据应使用 dataManager 对象
var data = {
    service: {
        _summary: "业务数据对象, 保存需要提交的表单数据"
    },
    cached: {
        _summary: "用于UI计算的缓存数据对象"
    },
    temporaries: {
        _summary: "临时数据集合"
    },
    _summary: "数据集合"
};

 

 

  • 约定数据维护对象(dataManager)

 

//  数据维护对象
var dataManager = {
    _summary: "数据维护对象, 提供 data 集合中数据计算能力"
};

 

 

  • 约定UI绘制程序集(UIPrinters)

 

// UI绘制对象
// HTML 控件/控件属性查找/编辑, 页面重绘等应统一使用该对象
var UIPrinters = {
    _summary: "UI界面绘制集合. 提供HTML控件查找, 编辑等能力; 如 getSearchConditionFormContainer, getCurrentPageNumber 等等"
};

 

 

  • 约定配置(业务)程序集(config)

 

// 配置(业务)集合
// 此对象配置业务模块化运算能力, 以及事件管理基础功能
var config = {
    serviceModules: {
        // FIXME example start
        download: {
            beforeValidPermission: function(callback) {
                var hasPermission = true;
                // Remote validation: requestUtil.jsonAjax();
                !!hasPermission && callback();
            },
            getChoseData: function() {
                // 调用前确保 dataManager.getCurrPageChoseData 已定义
                return dataManager.getCurrPageChoseData();
            },
            sendRequest: function(choseDataKeys) {
                // 调用前确保 UIPrinters.loadingWin 已定义
                UIPrinters.loadingWin.loading();
                // requestUtil.download(choseDataKeys);
                UIPrinters.loadingWin.completed();
            },
            invoke: function() {
                // downloadCtt -> Download Context
                var downloadCtt = config.events.download;
                downloadCtt.beforeValidPermission(function() {
                    var data = downloadCtt.getChoseData();
                    downloadCtt.sendRequest(data);
                });
            }, // FIXME example end
            _summary: "下载模块, 示例模块"
        },
        _summary: "业务集合. Key-模块名; Value:{Key:业务名, Value:处理函数}. 在每个模块中应定义_summary用以说明该模块的用途"
    },
    eventsManager: {
        events: {
            _summary: "事件列表, 为initRegister提供支撑"
        },
        initRegister: {
            delegate: function() {
                // TODO Register delegate events
                // 注册委托事件
                // 选择器使用 KEYS.SELECTORS, 如:
                // $(KEYS.SELECTORS.getSearchFormContainerSelector)
            },
            singleUse: function() {
                // TODO Register single-use events
                // 注册一次性事件
                // 选择器使用 KEYS.SELECTORS, 如:
                // $(KEYS.SELECTORS.getSearchFormContainerSelector)
            }
        },
        bind: {
            singleUse: function(item, eventType, eventFn) {
            },
            delegate: function(item, eventType, eventFn) {
            },
            _summary: "事件绑定"
        },
        unbind: {
            singleUse: function(item) {
            },
            delegate: function(item) {
            },
            _summary: "事件卸载, 如果删除元素时使用$el.remove(), 会自动卸载事件. 委托事件(delegate)需要根据实际情况考虑是否需要卸载"
        },
        _summary: "事件管理器, 用于支撑控件的事件绑定和卸载"
    },
    _summary: "本地配置实现, 提供业务逻辑支撑而不是实现"
};

 

 

  • 约定控制台(和/或发送到Server)的日志规范

 

// 独立的日志函数
// 善于利用浏览器提供的控制台(window.console)工具, 在很大程度上可以帮助 coder 们快速定位并解决现有问题
// 当前日志程序打印格式: [local-file:row-number] [caller|anonymous] [date] - message
// 打印格式可根据项目需求自行调整, 强烈建议保留 [local-file:row-number], 此信息能快速定位 .js 文件中的位置, 对于 Fix issue 非常有用. 此功能是我特意在 Google 中查找并加入的功能
function log(msg) {
    if ($thisObj.debug) {
        var formattedNow = new Date().format("yyyy-MM-dd hh:mm:ss");
        var caller = arguments.callee.caller.name;
        caller = caller || "Anonymous";
        var local = "__LOCATION__";
        var logPrefix = "[" + local + "] [" + caller + "] [" + formattedNow + "] - ";
        if (window.console) {
            try {
                throw new Error();
            } catch (e) {
                var callerInfo = e.stack.match(/\n.*/g)[1];
                callerInfo = callerInfo.match(/http:+.*[\d]/)[0];
                // callerInfo = callerInfo.replace(stringUtil.getBaseUrl(),
                // FINAL_VALUE.EMPTY_STRING);
                logPrefix = logPrefix.replace(local, callerInfo);
            }
            console.log(logPrefix + JSON.stringify(msg));
            (msg instanceof Object) && console.log(msg);
        }
    }
}

 

 

  满足上述约定后,Javascript 程序模板预览如下。

 

 

TestFn.debug = true;
TestFn.debug && window.console && console.log("test.js");
$(function() {
    TestFn.instance = new TestFn();
    TestFn.instance.initEvents().initData();
});

/**
 * @description test.jsp 页面交互
 * @author 
 * @version v1.0
 * @date 
 */
function TestFn() {
    var $thisObj = this;
    var baseCtnr = $(".test-body-container:eq(0)");

    /** 常量值集合 */
    var FINAL_VALUE = {
        KEYS: {
            CONFIG_KEYS: {
                _summary: "本地配置字典"
            },
            SELECTORS: {
                _summary: "jQuery选择器字典"
            },
            ATTRIBUTES: {
                _summary: "控件属性字典"
            },
            _summary: "关键字字典 "
        },
        VALUES: {
            _summary: "常量值字典"
        },
        _summary: "常量值字典. 使用getter实现, 如: getFinalPageSize"
    };

    /** 数据集合, 访问数据应使用 dataManager 对象 */
    var data = {
        service: {
            _summary: "业务数据对象, 保存需要提交的表单数据"
        },
        cached: {
            _summary: "用于UI计算的缓存数据对象"
        },
        temporaries: {
            _summary: "临时数据集合"
        },
        _summary: "数据集合"
    };

    /** 数据维护对象 */
    var dataManager = {
        _summary: "数据维护对象, 提供 data 集合中数据计算能力"
    };

    /** UI绘制对象 */
    var UIPrinters = {
        _summary: "UI界面绘制集合. 提供HTML控件查找, 编辑等能力; 如 getSearchConditionFormContainer, getCurrentPageNumber 等等"
    };

    /** 配置(业务)集合 */
    var config = {
        serviceModules: {
            // FIXME example start
            download: {
                beforeValidPermission: function(callback) {
                    var hasPermission = true;
                    // Remote validation: requestUtil.jsonAjax();
                    !!hasPermission && callback();
                },
                getChoseData: function() {
                    // 调用前确保 dataManager.getCurrPageChoseData 已定义
                    return dataManager.getCurrPageChoseData();
                },
                sendRequest: function(choseDataKeys) {
                    // 调用前确保 UIPrinters.loadingWin 已定义
                    UIPrinters.loadingWin.loading();
                    // requestUtil.download(choseDataKeys);
                    UIPrinters.loadingWin.completed();
                },
                invoke: function() {
                    // downloadCtt -> Download Context
                    var downloadCtt = config.events.download;
                    downloadCtt.beforeValidPermission(function() {
                        var data = downloadCtt.getChoseData();
                        downloadCtt.sendRequest(data);
                    });
                }, // FIXME example end
                _summary: "下载模块, 示例模块"
            },
            _summary: "业务集合. Key-模块名; Value:{Key:业务名, Value:处理函数}. 在每个模块中应定义_summary用以说明该模块的用途"
        },
        eventsManager: {
            events: {
                _summary: "事件列表, 为initRegister提供支撑"
            },
            initRegister: {
                delegate: function() {
                    // TODO Register delegate events
                    // 注册委托事件
                    // 选择器使用 KEYS.SELECTORS, 如:
                    // $(KEYS.SELECTORS.getSearchFormContainerSelector)
                },
                singleUse: function() {
                    // TODO Register single-use events
                    // 注册一次性事件
                    // 选择器使用 KEYS.SELECTORS, 如:
                    // $(KEYS.SELECTORS.getSearchFormContainerSelector)
                }
            },
            bind: {
                singleUse: function(item, eventType, eventFn) {
                },
                delegate: function(item, eventType, eventFn) {
                },
                _summary: "事件绑定"
            },
            unbind: {
                singleUse: function(item) {
                },
                delegate: function(item) {
                },
                _summary: "事件卸载, 如果删除元素时使用$el.remove(), 会自动卸载事件. 委托事件(delegate)需要根据实际情况考虑是否需要卸载"
            },
            _summary: "事件管理器, 用于支撑控件的事件绑定和卸载"
        },
        _summary: "本地配置实现, 提供业务逻辑支撑而不是实现"
    };

    /** 初始化事件 */
    this.initEvents = function() {
        try {
            config.eventsManager.initRegister.singleUse();
            config.eventsManager.initRegister.delegate();
        } catch (e) {
            log(e.message);
        }
        return $thisObj;
    };

    /** 初始化数据 */
    this.initData = function() {
        try {
            // 这里只定义函数的调用顺序, 而不应该直接在此编写实现代码
        } catch (e) {
            log(e.message);
        }
        return $thisObj;
    };

    // 日志记录
    function log(msg) {
        if ($thisObj.debug) {
            var formattedNow = new Date().format("yyyy-MM-dd hh:mm:ss");
            var caller = arguments.callee.caller.name;
            caller = caller || "Anonymous";
            var local = "__LOCATION__";
            var logPrefix = "[" + local + "] [" + caller + "] [" + formattedNow + "] - ";
            if (window.console) {
                try {
                    throw new Error();
                } catch (e) {
                    var callerInfo = e.stack.match(/\n.*/g)[1];
                    callerInfo = callerInfo.match(/http:+.*[\d]/)[0];
                    // callerInfo = callerInfo.replace(stringUtil.getBaseUrl(),
                    // FINAL_VALUE.EMPTY_STRING);
                    logPrefix = logPrefix.replace(local, callerInfo);
                }
                console.log(logPrefix + JSON.stringify(msg));
                (msg instanceof Object) && console.log(msg);
            }
        }
    }

    return this;
}

 

  为什么写此文章:

  1. 记录并分享工作总结也是一件乐事。如果能帮助别人岂不快哉^^.
  2. 养成写博文的习惯有助于总结工作中的有点, 找到自己的不足. 通常喜欢写博文的童鞋也会经常看别人的博文。记得在哪本书上(忘记是Code2还是Javascript高级编程哭)看到一句话: 读书就是把别人的经历变成自己的经验

   eclipse模板下载:

  由于不支持上传 .xml 文件, 在文件名中中添加了混淆 iteye 上传系统的多余后缀, 下载后去掉后缀即可导入eclipse工具了.

  Google javascript 格式化模板:google-js-formatter.xml

  上面提到的 Javascript 代码模板:yong-defined-js-templates.xml

   

  如何使用

  1. 导入模板到eclipse中(如何导入? 童鞋, 这么简单的问题不可能不会吧眨眼)
  2. 在编辑窗口中数据: $pagefn, $pagefn, $this, $thisobj, 激活上下文提示(alt + /)
1
0
分享到:
评论

相关推荐

    前端网页模板200套-html+css+JavaScript前端静态响应式页面模板(多级页面,交互响应式)

    它们通常包含基本的HTML、CSS和JavaScript代码,可供您根据自己的需求进行自定义。 含有不同种类风格的200套前端交互式静态页面,满足各种风格需求 静态网页模板:这些模板适用于构建简单的静态网页,如个人简历、...

    20套大屏可视化交互动态模板网页前端模板

    标题中的“20套大屏可视化交互动态模板网页前端模板”揭示了这个资源的核心内容,它是关于网页前端设计的,特别聚焦于大屏可视化的交互动态模板。这一领域通常涉及数据展示、信息图形化以及用户体验设计。下面将详细...

    HTML+CSS+JavaScript网页模板

    【HTML+CSS+JavaScript网页模板】是Web开发中常见的元素,它们构成了网页的基本结构、样式和交互性。HTML(HyperText Markup Language)是用于创建网页内容的标记语言,CSS(Cascading Style Sheets)则负责定义这些...

    180个javascript代码模板,每个都很小,但是全面

    JavaScript是一种广泛应用于网页和网络应用的编程语言,它在客户端和服务器端都能运行,使得网页具有动态交互性。本资源包含180个JavaScript代码模板,这些模板小巧却功能全面,能够帮助开发者快速解决常见的编程...

    [开源]可视化大数据交互动态模板网页前端模板.zip

    【开源]可视化大数据交互动态模板网页前端模板.zip是一个包含一系列资源的压缩包,主要用于创建交互式的、可视化的数据展示页面。这个模板基于HTML、JavaScript和CSS技术,为开发者提供了在网页上展示大数据的便捷...

    JavaScript经典模板

    在这个"JavaScript经典模板"中,我们可以看到一系列的示例,涵盖了不同功能的实现,包括图像操作、页面动态效果、时间处理以及用户交互等。接下来,我们将详细讨论这些知识点。 首先,我们注意到几个名为"LOGO*.gif...

    HTML+CSS+JavaScript前端模板

    模板中可能包含了一些JavaScript库,如jQuery,它简化了DOM操作和事件处理,还有可能有Vue.js或React.js这样的前端框架,用于构建组件化的应用。 此外,这个模板还可能包含了预处理器如Sass或Less,它们扩展了CSS的...

    可视化大数据交互动态模板网页前端模板_可视化大数据交互动态模板网页前端模板_

    本资源提供的"可视化大数据交互动态模板网页前端模板",就是一个专为展示大数据设计的交互式平台,虽然它不具备实际处理数据的能力,但作为一个模拟演示,可以帮助我们理解大数据可视化的基本原理和实现方式。...

    009_模拟可视化大数据交互动态模板网页前端_

    在IT行业中,模拟可视化大数据交互动态模板网页前端是一种常用的技术手段,主要用于设计和展示具有动态效果和交互功能的数据可视化界面。这样的模板可以帮助开发者快速构建出吸引人的数据展示平台,虽然它本身不具备...

    Qt5与Javascript交互

    首先,让我们理解Qt5与JavaScript交互的基础。Qt的WebEngine模块允许在C++应用中嵌入一个完整的WebKit或Chromium浏览器引擎,这使得开发者可以利用JavaScript来增强C++应用程序的用户界面。通过这种方式,开发者能够...

    基于HTML模板和JSON数据的JavaScript交互(移动端)_.docx

    【基于HTML模板和JSON数据的JavaScript交互(移动端)】是一种常见的前端开发技术,它结合了HTML模板和JSON数据,使得JavaScript能够动态地渲染和更新页面内容,尤其在移动端应用中非常常见。这种方法能够提高代码的...

    交互式bootstrap网站模板

    对于“网站模板”,它是预先设计好的HTML结构,包含样式和可能的JavaScript代码,开发者可以根据自己的需求进行定制。这些模板通常会涵盖多个页面,如首页、关于我们、服务、联系我们的页面,以及像"Notebook_admin...

    javascript项目实战 模板

    【标题】:“JavaScript项目实战模板...通过这些项目,学习者可以系统地学习JavaScript的各个核心领域,并在实践中不断提升自己的编程能力。同时,这些实战经验也能为将来在51Job或其他职业平台找工作时增加竞争优势。

    dashboard_javascript_dashboard模板_源码

    在实际应用中,开发者可以利用这个JavaScript仪表盘模板快速搭建一个数据展示平台,只需要根据自己的需求替换示例数据,调整样式,或者添加额外的功能。模板通常会提供良好的文档和示例,以便开发者了解如何初始化...

    JavaApplet与JavaScript交互方法的探讨.pdf

    【JavaApplet与JavaScript交互方法的探讨】 JavaApplet是一种早期的Web技术,它允许开发者在浏览器中嵌入可执行的Java代码,从而提供更丰富的交互性和动态功能。JavaApplet通常用于创建复杂的用户界面或者在Web页面...

    html5 css3 JavaScript响应式中文静态网页模板js源代码(400套网页模板)

    《HTML5 CSS3 JavaScript响应式中文静态网页模板与JS源代码详解》 在现代网页设计领域,HTML5、CSS3和JavaScript是构建响应式、交互性强的中文静态网页的三大核心技术。本篇将深入探讨这三者如何共同打造一套完整的...

    javascript进销存模板

    JavaScript进销存模板是一款基于JavaScript开发的库存管理系统模板,它主要应用于中小企业或个人进行商品的进货、销售和库存管理。这个模板可能包含了前端用户界面以及一些基础的数据处理逻辑,允许用户方便地记录和...

    JavaScript下拉菜单模板

    JavaScript下拉菜单模板是一种网页交互元素,用于在有限的空间内展示丰富的导航选项。在网页设计中,下拉菜单常用于网站导航,使用户能够轻松访问多层次的页面结构,而无需占用太多屏幕空间。这种菜单主要由...

    全屏自适应相册动画交互JS模板_相册 全屏 自适应 交互 旅游.zip

    此模板充分利用JavaScript语言的灵活性和强大功能,为用户提供了一个既美观又实用的展示照片的方式,特别适合于旅游类网站或者个人旅行照片分享。 首先,全屏设计是现代网页设计的趋势,它能最大化地展示图像,让...

Global site tag (gtag.js) - Google Analytics