大前端之前后分离02】前端模板嵌套问题

简介:

接上文:【大前端之前后分离01】JS前端渲染VS服务器端渲染,我们探讨了为什么要做前后分离,以及前端渲染需要解决的问题,最后提出了自己的解决方案:

前端代码编译形成两套代码:①前端发布版本 + ②服务器端脚本
这个想法借鉴了fis plus的smarty模块化思维,以及reactJS编译运行的概念,上次初步论证了其可行性,也遗留了一些问题,其中比较关键的问题是:

前端模块嵌套问题
我们在一个模板中又有一个widget,在子模板中又有一个widget,父模块与子模块中有数据依赖,或者子模块为一个循环,循环却依赖父模块某个值,这个便很麻烦。

举个例子来说,我们首页引入了一个商品模块,商品类型模块为一循环模块,里面又有子模块:

index首页模块:

1 <div id="type_widget_wrapper">
2   <script type="text/javascript">
3     render('text!./template/type.html', './model/type', './controller/type', 'type_widget_wrapper');
4   </script>
5 </div>
type模块:

复制代码
 1 <ul id="type_id">
 2     <% for (var i = 0, len = data.length; i < len; i++) { %>
 3     <li class="type js_type">
 4         <h2><%=data[i].name%></h2>
 5         <ul class="product_list">
 6             <% for (var j = 0, len1 = data[i].product.length; j < len1; j++) { %>
 7                 <li class="product">
 8                     <%=data[i].product[j].name%>
 9                 </li>
10             <% } %>
11         </ul>
12     </li>
13     <% } %>
14 </ul>
复制代码
可以看到,其中有第二次循环迭代的将该类型的商品信息读出,如果我们想将商品信息模块化的,这里便出现了模块嵌套情况:

复制代码
 1 <ul id="type_id">
 2     <% for (var i = 0, len = data.length; i < len; i++) { %>
 3     <li class="type js_type">
 4         <h2><%=data[i].name%></h2>
 5         <ul class="product_list">
 6         <div id="product_list_widget_wrapper">
 7           <script type="text/javascript">
 8             render('text!./template/product_list.html', './model/product_list', './controller/product_list', 'product_list_widget_wrapper');
 9           </script>
10         </div>
11         </ul>
12     </li>
13     <% } %>
14 </ul>
复制代码
这里暂时不考虑子模块中还有异步数据请求问题,我们将列表对应的模板放到了单个文件中:

1 <% for (var j = 0, len1 = data[i].product.length; j < len1; j++) { %>
2     <li class="product">
3         <%=data[i].product[j].name%>
4     </li>
5 <% } %>
这里的循环解析便是我们今天研究的重点,因为前端模块至少需要两个条件:

① 唯一的dom容器

② 能获取父级模块的相关数据

为了解决这个问题,我这里提出了迭代模块的概念。

迭代模块

所谓迭代模块,便是用于数据内嵌形式,并且处于循环中的模块,比如上述例子,我整个type模板就变成了这样(这里为最简形式):

复制代码
 1 <ul id="type_id">
 2   <% for (var i = 0, len = data.length; i < len; i++) { %>
 3   <li class="type js_type">
 4     <h2>
 5       <%=data[i].name%></h2>
 6     <ul class="product_list">
 7 
 8       <div id="data_inner_widget_wrapper_<%=i %>">
 9         <script type="text/javascript">
10           iteratorRender({
11             index: typeof <%=i%> == 'string' ? '<%=i%>' : <%=i%>,
12             value: <%=JSON.stringify(data[i])%>,
13             name: 'data_inner'
14           });
15         </script>
16       </div>
17 
18     </ul>
19   </li>
20   <% } %>
21 </ul>
复制代码
这个是编译过后形成的前端代码,最初是这样的:

复制代码
 1 <ul id="type_id">
 2   <% for (var i = 0, len = data.length; i < len; i++) { %>
 3   <li class="type js_type">
 4     <h2>
 5       <%=data[i].name%></h2>
 6     <ul class="product_list">
 7         <%iteratorWidget({
 8           index: <%=i%>,
 9           value: <%=JSON.stringify(data[i])%>,
10           name: 'data_inner',
11         }); %>
12     </ul>
13   </li>
14   <% } %>
15 </ul>
复制代码
1 <%iteratorWidget({
2   index: <%=i%>, //索引,整数或者字符串
3   value: <%=JSON.stringify(data[i])%>, //对应数据对象,字符串或者json对象
4   name: 'data_inner',
5 }); %>
这个时候前端需要实现iteratorRender方法,首先前端模板将上述代码解析结束后是这个样子的:

 View Code
复制代码
 1 <li class="type js_type">
 2   <h2>
 3     电脑</h2>
 4   <ul class="product_list">
 5 
 6     <div id="data_inner_widget_wrapper_0">
 7       <script type="text/javascript">
 8         iteratorRender({
 9           index: typeof 0 == 'string' ? '0' : 0,
10           value: { "id": 1, "name": "电脑", "product": [{ "name": "戴尔" }, { "name": "苹果" }, { "name": "联想" }, { "name": "华硕"}] },
11           name: 'data_inner'
12         });
13       </script>
14     </div>
15 
16   </ul>
17 </li>
复制代码
然后前端方法的实现为:

复制代码
 1 //最简单实现,仅考虑渲染,不严谨
 2 var iteratorRender = function (opts) {
 3   var name = opts.name;
 4   var index = opts.index;
 5   var data = typeof opts.value == 'string' ? JSON.parse(opts.value) : opts.value;
 6   var wrapperId = name + '_widget_wrapper_' + index;
 7   var template = 'text!./template/' + name + '.html';
 8   var controller = './controller/' + name;
 9 
10   require([template, controller], function (tpl, view) {
11     var html = $(_.template(tpl)(data));
12     var wrapper = $('#' + wrapperId);
13     html.insertBefore(wrapper);
14     wrapper.remove();
15     //执行控制器
16     view.init();
17   });
18 }
复制代码
然后代码运行,逻辑跑通了:



结语

由于最近工作强度上来了,解决了前端渲染时候的模板嵌套问题,一直拖到了今天,服务器端的模板嵌套更好处理,该方案后续会继续细


本文转自叶小钗博客园博客,原文链接http://www.cnblogs.com/yexiaochai/p/4492170.html,如需转载请自行联系原作者

相关文章
|
设计模式 前端开发 搜索推荐
前端必须掌握的设计模式——模板模式
模板模式(Template Pattern)是一种行为型设计模式,父类定义固定流程和步骤顺序,子类通过继承并重写特定方法实现具体步骤。适用于具有固定结构或流程的场景,如组装汽车、包装礼物等。举例来说,公司年会节目征集时,蜘蛛侠定义了歌曲的四个步骤:前奏、主歌、副歌、结尾。金刚狼和绿巨人根据此模板设计各自的表演内容。通过抽象类定义通用逻辑,子类实现个性化行为,从而减少重复代码。模板模式还支持钩子方法,允许跳过某些步骤,增加灵活性。
1063 11
|
JSON 前端开发 API
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
1149 5
以项目登录接口为例-大前端之开发postman请求接口带token的请求测试-前端开发必学之一-如果要学会联调接口而不是纯写静态前端页面-这个是必学-本文以优雅草蜻蜓Q系统API为实践来演示我们如何带token请求接口-优雅草卓伊凡
|
前端开发 JavaScript
前端基础(六)_流程控制语句(if、if-else、if-else嵌套、switch)
本文介绍了JavaScript中的流程控制语句,包括if、if-else、if-else嵌套和switch语句。
405 2
前端基础(六)_流程控制语句(if、if-else、if-else嵌套、switch)
|
前端开发 JavaScript 开发者
超实用开源前端商城模板,助力电商项目飞速启航!免费直接可用!
分享一款精心设计的开源前端商城模板,涵盖商品展示、购物车、订单处理、用户登录注册等核心功能,使用HTML、CSS、JS和jQuery构建,结构清晰,适合新手和资深开发者,助力电商项目快速启动。
1394 0
超实用开源前端商城模板,助力电商项目飞速启航!免费直接可用!
|
JavaScript 前端开发 Java
SpringBoot + Vue 前端后分离项目精进版本
这篇文章详细介绍了一个基于SpringBoot + Vue的前后端分离项目的搭建过程,包括前端Vue项目的初始化、依赖安装、页面创建和路由配置,以及后端SpringBoot项目的依赖添加、配置文件修改、代码实现和跨域问题的解决,最后展示了项目运行效果。
SpringBoot + Vue 前端后分离项目精进版本
|
前端开发
前端使用xlsx模板导出表格
【9月更文挑战第10天】在前端使用 `xlsx` 模板导出表格需完成以下步骤:首先引入 `xlsx` 库,准备数据与模板;接着读取模板文件,选择特定工作表并填充数据;最后将填充后的表格转换为二进制数据,创建 Blob 对象并触发下载。整个过程中可根据需求调整模板格式和数据填充方式。
777 6
|
开发者 容器 Docker
JSF与Docker,引领容器化浪潮!让你的Web应用如虎添翼,轻松应对高并发!
【8月更文挑战第31天】在现代Web应用开发中,JSF框架因其实用性和灵活性被广泛应用。随着云计算及微服务架构的兴起,容器化技术变得日益重要,Docker作为该领域的佼佼者,为JSF应用提供了便捷的部署和管理方案。本文通过基础概念讲解及示例代码展示了如何利用Docker容器化JSF应用,帮助开发者实现高效、便携的应用部署。同时也提醒开发者注意JSF与Docker结合使用时可能遇到的限制,并根据实际情况做出合理选择。
359 0
|
前端开发 JavaScript API
前端的全栈之路Meteor篇(完):关于前后端分离及与各框架的对比,浅析分离之下的潜在耦合
本文探讨了Meteor.js这一全栈JavaScript框架的特点与优势,特别是在前后端分离架构中的应用。Meteor通过共享数据结构和简化全栈开发流程,实现了前后端的紧密协作。文章还对比了其他全栈框架,如Next.js、Nuxt.js等,分析了各自的优势与适用场景,最后讨论了通过定义文档归属者和用户专有数据集简化后端构建及端云数据同步的方法。
1460 0
|
开发框架 前端开发 JavaScript
循序渐进VUE+Element 前端应用开发(33)--- 邮件参数配置和模板邮件发送处理
循序渐进VUE+Element 前端应用开发(33)--- 邮件参数配置和模板邮件发送处理
|
缓存 JavaScript 前端开发
前端框架与库 - Vue.js基础:模板语法、数据绑定
【7月更文挑战第14天】Vue.js 是渐进式框架,以简洁API和高效数据绑定知名。本文聚焦模板语法与数据绑定,解释常见问题和易错点,助力初学者避坑。模板语法中,{{ expression }} 用于渲染值,v-bind/: 用于动态绑定属性。数据绑定涉及文本、属性和事件,注意v-model适用于表单元素,计算属性有缓存。理解正确用法,借助文档和IDE,可提升开发质量和效率。善用Vue.js,打造响应式UI。
715 4

热门文章

最新文章

  • 1
    前端如何存储数据:Cookie、LocalStorage 与 SessionStorage 全面解析
    1380
  • 2
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(九):强势分析Animation动画各类参数;从播放时间、播放方式、播放次数、播放方向、播放状态等多个方面,完全了解CSS3 Animation
    657
  • 3
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(八):学习transition过渡属性;本文学习property模拟、duration过渡时间指定、delay时间延迟 等多个参数
    510
  • 4
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(七):学习ransform属性;本文学习 rotate旋转、scale缩放、skew扭曲、tanslate移动、matrix矩阵 多个参数
    516
  • 5
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(六):全方面分析css的Flex布局,从纵、横两个坐标开始进行居中、两端等元素分布模式;刨析元素间隔、排序模式等
    615
  • 6
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(五):背景属性;float浮动和position定位;详细分析相对、绝对、固定三种定位方式;使用浮动并清除浮动副作用
    798
  • 7
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(四):元素盒子模型;详细分析边框属性、盒子外边距
    1582
  • 8
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(三):元素继承关系、层叠样式规则、字体属性、文本属性;针对字体和文本作样式修改
    369
  • 9
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(二):CSS伪类:UI伪类、结构化伪类;通过伪类获得子元素的第n个元素;创建一个伪元素展示在页面中;获得最后一个元素;处理聚焦元素的样式
    1299
  • 10
    【CSS】前端三大件之一,如何学好?从基本用法开始吧!(一):CSS发展史;CSS样式表的引入;CSS选择器使用,附带案例介绍
    630