• 模版+数据分离渲染方式的设计与实现


    一 背景
    1 现状
    • 模版存放于后端
    • php输出页面html结构进行页面渲染
    • ajax请求,需要重渲结构时,php输出html结构
    • builder制作静态页面结构
    • jser完成页面交互逻辑开发
    2 不足
    • 模版数据无法存储本地,导致每次打开页面请求数据量巨大
    • 数据每次要从接入层web服务器读取,没有合理利用CDN加速静态模版内容
    • 联调成本较大,不利于前端控制页面展示和交互开发
    3 解决方案
    • 后端直接输出json数据
    • 试图把渲染页面的模版存放在前端
    4 技术路线
     
    5 理论意义
    • 利用CDN保存html模版,看起来第一次请求会使用多一点的资源,实际上消耗并不是很大,且多次请求可以减小下载量
    • 充分利用缓存,提高性能
    • 联调成本大大降低,后端只需要按规则输出Json数据,前端能更大程度的控制页面展示,减小bug量
    二 基于模版与数据分离渲染方式的方案设计
    1 ejs模版简介
            官方API地址:http://www.embeddedjs.com/
            官方API介绍的很清楚,也是大多数模版的常用办法。下面列举几个特殊用法:
    • 可自定义函数
             支持常用html标签的快捷方式,就像ruby on rails framework的做法一样,让代码更简洁。
    • 支持模版错误提示

    • 另外,ejs支持nodejs
    2 pageletView渲染组件简介
    • pageletView按照页面的模块分别输出模块id,css,js,html
    3 ejs与pageletView的融合方案设计
            pageView在渲染页面的时候,是分模块进行渲染的。这种方式是实现bigpipe的重要渲染方式,那么需要我们在不改变原有pageview的基础上进行改造。
    即在原有的技术上,多传给STK.pageletM.view方法参数的两个属性,一个属性命名为data,用来存放json数据传递给前端使用,另一个属性命名为template,用来存放模块的模版文件。

    然而,由于页面上有多少个模块,就会有多少个template文件,在实现完成这种渲染之后,发现如果一个页面上的模块比较多的话,就会给页面渲染带来一定的负担,所以决定把一个页面的模版合并成一个模版文件,这样只需要请求一次模版文件就可以了。设计如下:

    三 基于模版与数据分离渲染方式的实现
    1模版的传递办法
            ejs拿到模版和数据后,执行渲染。数据可以在pageLet拿到数据的时候,通过参数传递,而每个模块的渲染,需要动态的传递模块template,不 可能直接$Import写死到ejs文件,也不可能$Import写死到pageletView文件里。这个问题有两种办法解决。
    • 把模版设置成全局变量
    • 使用listener广播事件监听

    显然,第一种把模版设置成全局变量的办法有很大风险,容易造成混淆和错乱,切不利于维护。于是我们选择第二种办法,listener事件广播的形式。因为 第二种办法,在需要使用到模版的地方,我们通过架设管道的方式,一对一的监听模版发出的广播,从ejs模版里进行接收,这样就避免了抛到全局造成的问题。

     
    2 实现无等待的模版渲染
            然而,在使用listener事件的时候又遇到了问题。
            因为熟悉listener事件的同学都知道,事件fire与事件register是有先后顺序的,register在前,fire在后,也就是说在ejs 需要使用模版的时候,我们会使用listener的register方法绑定事件,然后才可以把模版fire出来,那么我们很容易想到把合并完的模版文件 a.js放在pageletView渲染模块之后,但是放在后面我们是无法监听到对应模块的pageletView已经register完成的,这时候如 果使用setTimeout的方式虽然能够解决问题但是存在着很大的弊端,因为第一,setTimeout需要耗费性能,渲染出页面的体验非常差,第二, 我们做了个测试,如果setTimeout的时间参数小于1000ms的话,成功渲染所有模块只能成为偶发的事情。
            怎么解决这个问题呢,我们最后想到了一个办法,使用两个广播进行解决。
            首先,我们把模版合并好的a.js文件放在pageletM(pageletM会调用pageletView方法)渲染之前,register一个广播,广播的名字叫做id+’_temp’,在这个广播里我们去把模版fire出去,fire的参数为id。
         
            其次,我们在ejs文件里register一个事件,这个参数为模块的id(即pid),然后fire一个事件,fire的参数为id+’_temp’
         
     
            整个传递的步骤为:
            首先ejs文件监听模版文件,然后模版文件fire出模版,整个目的就达到了。
            这个过程描述如图:
            说明:首先页面加载模版文件,模版文件监听pageletView文件reday的listener事件,回调函数fire出“模版”,然后页面运行 pageletView文件,pageletView文件注册了模版文件ready的事件,然后再pageView文件里发出模版pagelet已经 ready的信号。这样在pageletView执行的时候,模版告诉pageletView模版已经ready,监听过模板ready的回调函数就可以 收到模版从而完成模板与数据拼接了。这样就实现了无等待的数据加模版渲染。
         
     
    3 pageletView中的向下兼容
             由于微博现如今使用的方式是模版放在后端进行,前端取到后端传出的html,然后进行渲染,若使用template+data的方式进行页面渲染,我们 可以做一下向下兼容。如下图,判断若data != undefined则通过template+data进行渲染,否则使用原有的方式进行渲染。
         
    4 实现trans请求的模版渲染
            大家知道,前端对后端ajax请求成功的时候,若前端需要改变某个节点的innerHTML,后端会返回一段html代码,而当我们点击feed分页的时 候,可能会浪费大量的模版流量,如果把模版存在前端,后端只需要提供每个feed需要的数据就可以了,这个可以节省很多资源。
            实现这种方式很简单,只需要按照pageletView中的使用方式就可以了,但是这样的话会存在一个问题。前端拿到模版和数据拼接好html结构后,需 要知道怎么去处理这段html,所以我们把insertHTML集成在ejs中,通过传递参数的形式,去让ejs执行innerHTML或者是 insertHTML(如下图)。
         
     5 实现ejs文件的简单使用
            每次使用可能我们都需要注册一个事件,并在这个事件内抛出另一个事件,使用起来非常不方便。经过分析与设计,我们决定把模版中的注册事件和fire事件封装起来,调用的过程中只需要传递几个参数就可以实现效果。如下图:
     
            模版文件引用sedEjsTemplate.js,业务文件引用$.kit.dom.ejs文件(pageletView对$.kit.ejs的引用是一种特例)。
                   
     
     
    6 template+data使用步骤(非常简单好用)
            第一步:写模版文件。
                        
     
            第二步:使用$.kit.dom.ejs();
              
            参数说明:
  • 相关阅读:
    iTerm2分屏快捷键
    k8s中运维/测试常用的命令整理(随时更新)
    httpRunner自动化测试用例使用笔记
    Git学习笔记-快速上手(mac系统)
    RBAC权限控制逻辑笔记
    CPS中有关CICD的配置
    LDAP中filter的使用
    Docker初级入门
    C语言 实现 HashTable
    从三个线程 排队打印 , 到 多个线程打印
  • 原文地址:https://www.cnblogs.com/dsphper/p/4218994.html
Copyright © 2020-2023  润新知