Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >Widget模式

Widget模式

作者头像
WindRunnerMax
发布于 2021-01-14 02:24:51
发布于 2021-01-14 02:24:51
1.1K00
代码可运行
举报
文章被收录于专栏:Czy‘s BlogCzy‘s Blog
运行总次数:0
代码可运行

Widget模式

Widget模式是指借用Web Widget思想将页面分解成组件,针对部件开发,最终组合成完整的页面,Web Widget指的是一块可以在任意页面中执行的代码块,Widget模式不属于一般定义的23种设计模式的范畴,而通常将其看作广义上的架构型设计模式。

描述

模块化开发使页面的功能细化,逐一实现每个功能模块来完成系统需求,这是一种很好的编程实践,在简单模板模式实现的模板引擎的帮助下可以非常方便的完成这个实例,这将更适合多人团队开发,降低相互之间因为功能或者视图创建的耦合影响概率,组件的多样化也能够组建更加丰富的页面,同样也会让组件的复用率提高。

实现

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// dom.js
F.module("./dom", function() {
    return {
        g: function(id) {
            return document.getElementById(id);
        },
        html: function(id, html) {
            if (!html) return this.g(id).innerHTML;
            else this.g(id).innerHTML = html;
        }
    }
});
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// template.js
F.module("./template", function() {

/***
 *   模板引擎,处理数据的编译模板入口
 *   @param  str     模块容器id或者模板字符串
 *   @param  data    渲染数据
 **/
var _TplEngine = function(str, data) {
    // 如果数据是数组
    if (data instanceof Array) {
        // 缓存渲染模板结果
        var html = "";
        // 数据索引
        var i = 0;
        // 数据长度
        var len = data.length;
        // 遍历数据
        for (; i < len; i++) {
            // 缓存模板渲染结果,也可以写成
            // html += arguments.callee(str, data[i]) ;
            html += _getTpl(str)(data[i]);
        }
        // 返回模板渲染最终结果
        return html;
    } else {
        // 返回模板渲染结果
        return _getTpl(str)(data);
    }
};
/***
 *   获取模板
 *   @param  str 模板容器id,或者模板字符串
 **/
var _getTpl = function(str) {
    // 获取元素
    var ele = document.getElementById(str);
    // 如果元素存在
    if (ele) {
        // 如果是input或者textarea表单元素,则获取该元素的value值,否则获取元素的内容
        var html = /^(textarea | input)$/i.test(ele.nodeName) ? ele.value : ele.innerHTML;
        // 编译模板
        return _compileTpl(html);
    } else {
        // 编译模板
        return _compileTpl(str);
    }
};
// 处理模板
var _dealTpl = function(str) {
    // 左分隔符
    var _left = "{%";
    // 右分隔符
    var _right = "%}";
    // 显示转化为字符串
    return String(str)
        // 转义标签内的<如:<div>{%if(a&lt;b)%}</div> -> <div>{%if(a<b)%}</div>
        .replace(/&lt;/g, "<")
        // 转义标签内的>
        .replace(/&gt;/g, ">")
        // 过滤回车符,制表符,回车符
        .replace(/[\r\t\n]/g, "")
        // 替换内容
        .replace(new RegExp(_left + "=(.*?)" + _right, "g"), "',typeof($1) === 'undefined' ? '' : $1, '")
        // 替换左分隔符
        .replace(new RegExp(_left, "g"), "');")
        // 替换右分隔符
        .replace(new RegExp(_right, "g"), "template_array.push('");

};
/***
 *   编译执行
 *   @param  str 模板数据
 **/
var _compileTpl = function(str) {
    // 编译函数体
    var fnBody = "var template_array=[];\nvar fn=(function(data){\nvar template_key='';\nfor(key in data){\ntemplate_key +=(''+key+'=data[\"'+key+'\"];');\n}\neval(template_key);\ntemplate_array.push('" + _dealTpl(str) + "');\ntemplate_key=null;\n})(templateData);\nfn=null;\nreturn template_array.join('') ;";
    // 编译函数
    return new Function("templateData", fnBody);
};

// 返回
return _TplEngine;
});
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<!-- demo.html -->
<!DOCTYPE html>
<html>

<head>
    <title>Widget模式</title>
</head>

<body>
    <div id="app"></div>
</body>
<script type="text/javascript">
(function(F) {
    const moduleCache = {};

    function getUrl(moduleName) {
        return String(moduleName).replace(/\.js$/g, "") + ".js"
    }

    function loadScript(src) {
        let _script = document.createElement("script");
        _script.type = "text/javascript";
        _script.charset = "UTF-8";
        _script.async = true;
        _script.src = src;
        document.body.appendChild(_script);
    }

    function setModule(moduleName, params, callback) {
        let _module = null,
            fn = null;
        if (moduleCache[moduleName]) {
            _module = moduleCache[moduleName];
            _module.status = "loaded";
            _module.exports = callback ? callback.apply(_module, params) : null;
            while (fn = _module.onload.shift()) {
                fn(_module.exports)
            }
        } else {
            callback && callback.apply(null, params);
        }
    }

    function loadModule(moduleName, callback) {
        let _module = "";
        if (moduleCache[moduleName]) {
            _module = moduleCache[moduleName];
            if (_module.status === "loaded") {
                // 这个很重要,loadModule一定是异步的,effectiveJS 上的某一条建议有写,永远不要同步的调用异步函数,这非常重要
                setTimeout(callback(_module.exports), 0);
            } else {
                // 加载完成的时候调用
                _module.onload.push(callback);
            }
        } else {
            // 第一次加载
            moduleCache[moduleName] = {
                moduleName: moduleName,
                status: "loading",
                exports: null,
                onload: [callback]
            };
            loadScript(getUrl(moduleName));
        }
    }

    F.module = function(...args) {
        // 获取模块构造函数(参数数组中最后一个参数成员)
        let callback = args.pop();
        // 获取依赖模块(紧邻回调函数参数,且数据类型为数组)
        let deps = (args.length && args[args.length - 1] instanceof Array) ? args.pop() : [];
        // 该模块url(模块ID)
        let url = args.length ? args.pop() : null;
        //  依赖模块序列
        let params = [];
        // 未加载的依赖模块数量统计
        let depsCount = 0;

        if (deps.length) {
            deps.forEach((v, i) => {
                // 增加未加载依赖模块数量统计
                depsCount++;
                // 异步加载依赖模块
                loadModule(deps[i], function(mod) {
                    // 依赖模块序列中添加依赖模块数量统一减一
                    depsCount--;
                    params[i] = mod;
                    // 如果依赖模块全部加载
                    if (depsCount === 0) {
                        // 在模块缓存器中矫正该模块,并执行构造函数
                        setModule(url, params, callback);
                    }
                });
            })
        } else { // 无依赖模块,直接执行回调函数
            // 在模块缓存器中矫正该模块,并执行构造函数
            setModule(url, [], callback);
        }
    }

})((() => window.F = ({}))());
</script>
<!-- srcpt模板内容 -->
<script type="text/template" id="tpl">
    <div id="tag_cloud">
        {% for(var i = 0; i < tagCloud.length; i++){ 
            var ctx = tagCloud[i] ; %}
        <a href="#" class="tag_item 
            {% if(ctx["is_selected"]){ %}
            selected
            {% } %}" title="{%=ctx["title"]%}">{%=ctx["text"]%}
        </a>
        {% } %}
    </div>
</script>
<!-- 自定义模板 -->
<!--===============模板种类结束===========-->
<script type="text/javascript">
// 模拟数据
var data = {
    tagCloud: [
        { is_selected: true, title: "Pattern", text: "设计模式" },
        { is_selected: false, title: "HTML", text: "HTML" },
        { is_selected: null, title: "CSS", text: "CSS" },
        { is_selected: "", title: "JavaScript", text: "JavaScript" },
    ]
}


F.module(["./template", "./dom"], function(template, dom) {
    // 服务器端获取到data数据逻辑
    // 创建组件视图逻辑
    var str = template("tpl", data);
    dom.html("app", str);
    // 组件其他交互逻辑
});
</script>
</html>

每日一题

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://github.com/WindrunnerMax/EveryDay

参考

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
https://en.wikipedia.org/wiki/Web_widget
https://segmentfault.com/a/1190000019541819
https://blog.csdn.net/yuzhiboyouzhu/article/details/78998860
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021-01-12 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
异步模块模式
异步模块模式AMD是当请求发出后,继续其他业务逻辑,直到模块加载完成执行后续逻辑,实现模块开发中的对模块加载完成后的引用,大名鼎鼎的require.js就是以它为思想的,异步模块模式不属于一般定义的23种设计模式的范畴,而通常将其看作广义上的架构型设计模式。
WindRunnerMax
2021/01/14
4500
前端工程化--Vue-CLI自动生成页面
按照上述操作以后,才可以正常访问新添加的页面,之后才开始对新页面进行正常开发。但是这样的机械化步骤我们完全可以用代码帮我们执行,更进一步,对于一些简单的页面,我们甚至可以一键生成页面,包括从后端请求数据等操作。
从入门到进错门
2020/04/10
2.1K0
前端工程化-自动生成vue页面
按照上述操作以后,才可以正常访问新添加的页面,之后才开始对新页面进行正常开发。但是这样的机械化步骤我们完全可以用代码帮我们执行,更进一步,对于一些简单的页面,我们甚至可以一键生成页面,包括从后端请求数据等操作。
江一铭
2022/06/16
1.4K0
从零开始学 Web 之 Ajax(七)跨域
跨域这个概念来自一个叫 “同源策略” 的东西。同源策略是浏览器上为了安全考虑实施的非常重要的安全机制。
Daotin
2018/08/31
3.5K0
如何实现VM框架中的数据绑定
作者:佳杰 本文原创,转载请注明作者及出处 如何实现VM框架中的数据绑定 一:数据绑定概述 视图(view)和数据(model)之间的绑定 二:数据绑定目的 不用手动调用方法渲染视图,提高开发效率;统一处理数据,便于维护 三:数据绑定中的元素 视图(view):说白了就是html中dom元素的展示 数据(model):用于保存数据的引用类型 四:数据绑定分类 view > model的数据绑定:view改变,导致model改变 model > view的数据绑定:model改变,导致view改变 五:数
iKcamp
2018/03/30
3.2K0
如何实现VM框架中的数据绑定
简单模板模式
简单模板模式是通过格式化字符串拼接出视图避免创建视图时大量的节点操作,简单模板模式不属于通常定义的设计模式范畴。
WindRunnerMax
2020/12/16
5680
ajax
PostMan下载地址:https://www.postman.com/downloads/
roydonGuo
2022/11/02
2.2K0
ajax
Emlog非插件实现3D标签云
第一步 module找到你的侧边栏标签 修改侧边栏标签如下 <?php //3D标签云 function widget_tag($title){ global $CACHE; $tag_cache =
若志奕鑫
2021/12/23
3870
Emlog非插件实现3D标签云
动手实现一个AMD模块加载器(二)
在上一篇文章中,我们已经基本完成了模块加载器的基本功能,接下来来完成一下路径解析的问题。
用户1515472
2019/07/24
6620
一篇文章,Vue快速入门!!!
MVVM源自于经典的MVC(Model-View-Controller)模式。MVVM的核心是ViewModel层,负责转换Model中的数据对象来让数据变得更容易管理和使用。其作用如下:
全栈程序员站长
2022/08/19
1.9K0
一篇文章,Vue快速入门!!!
thymeleaf中使用layui
头部引入css,尾部引入js,定义两个模板(一个也可以,里面的碎片分开写,我喜欢写两个分别引入),注意th:fragment,fragment即碎片,可以在模板任何位置引入,此处为分别定义名为header和js_footer的碎片,以供后面引用
小尘哥
2018/08/15
6.8K0
thymeleaf中使用layui
模板语法的简单实现
模板语法允许在HTML中之插入Js变量以及表达式,当在Js中控制render的时候能够自动在页面上将变量或者是表达式进行计算并显示,比较常见的模板语法有mustcache风格的{{}}以及DSL风格的dsl-html等。
WindRunnerMax
2020/08/27
9460
狂神说java系列笔记下载(跟狂神相似的小说)
​ 想要成为真正的“互联网Java全栈工程师”还有很长的一段路要走,其中前端是绕不开的一门必修课。本阶段课程的主要目的就是带领Java后台程序员认识前端、了解前端、掌握前端,为实现成为“互联网Java全栈工程师”再向前迈进一步。
全栈程序员站长
2022/08/01
1.9K0
狂神说java系列笔记下载(跟狂神相似的小说)
Lilac纳新赛web部分题目wp - wuuconix's blog
源码中没有flag,考虑flag在git以前的版本中,利用git log查看历史版本。
wuuconix
2023/03/13
3950
Lilac纳新赛web部分题目wp - wuuconix's blog
【图文并茂,点赞收藏哦!】重学巩固你的Vuejs知识体系
置身世外只为暗中观察!!!Hello大家好,我是魔王哪吒!重学巩固你的Vuejs知识体系,如果有哪些知识点遗漏,还望在评论中说明,让我可以及时更新本篇内容知识体系。欢迎点赞收藏!
达达前端
2022/04/13
1.7K0
【图文并茂,点赞收藏哦!】重学巩固你的Vuejs知识体系
3d标签云实现过程(tagcloud.js)同步原生和 vue
何处锦绣不灰堆
2023/11/23
8880
3d标签云实现过程(tagcloud.js)同步原生和 vue
【前端大神面考面试官系列】入门Vue全家桶
达达回答:Vue的安装可以从两个方面进行安装,第一种是CDN引入,第二种是NPM安装。
达达前端
2022/04/13
1.3K0
【前端大神面考面试官系列】入门Vue全家桶
快来领取,33个常用JavaScript功能已封装成方法,拿来即用
在实际开发中,为了提高开发的效率,我们会把常用到的功能封装成方法,这样后期开发需要,拿来即用。
艾编程
2022/12/04
2.8K0
快来领取,33个常用JavaScript功能已封装成方法,拿来即用
前端MVC学习总结(二)——AngularJS验证、过滤器、指令
一、验证 angularJS中提供了许多的验证指令,可以轻松的实现验证,只需要在表单元素上添加相应的ng属性,常见的如下所示: <input Type="text" ng-model="" [name
张果
2018/01/04
15.4K0
前端MVC学习总结(二)——AngularJS验证、过滤器、指令
最简单的JavaScript模板引擎
 在小公司待久了感觉自己的知识面很小,最近逛博客园和一些技术网站看大家在说JavaScript模版引擎的事儿,完全没有概念,网上一搜这是08年开始流行起来的。。。本来以为这是很高深的知识,后来在网上看到jQuery作者John Resig,研究了一下,算是明白了最简单的javaScript模版引擎的原理,并没有想象的那么高大上,写篇博客推导一下John Resig写法的过程,写出一个最简单的JavaScript模版引擎。
bear_fish
2018/09/19
1.7K0
最简单的JavaScript模板引擎
相关推荐
异步模块模式
更多 >
领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文