博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
基于fis3的组件可视化道路
阅读量:4886 次
发布时间:2019-06-11

本文共 10087 字,大约阅读时间需要 33 分钟。

  首先说明一下,即使不熟悉fis3,阅读文本应该也会有所收获。

  本文以fis-parser-imweb-tplv2插件为模板插件,目的不在于使用哪个模板,而是组件可视化的实现思路,不必担心。

 

先说说模板插件

  首先说明一下,我们的项目使用的fis3自带的mod.js做模块化开发。

  fis-parser-imweb-tplv2插件是同事在imweb待着的时候写的。模板使用和jsp写法一致,文件类型为tpl类型

  实现源码也比较简单易懂。fis3的配置

.match(/\/(.+)\.tpl$/, { // js 模版一律用 .tpl 作为后缀        isMod: true,        rExt: 'js',        id: '$1.tpl',        url: '$0.tpl',        moduleId: '$1.tpl',        release: '$0.tpl', // 发布的后的文件名,避免和同目录下的 js 冲突        parser: fis.plugin('imweb-tplv2')    })

  最终生成的模块化的.tpl.js文件如下

define('common/module/rightsideBar/rightsideBar.tpl', function(require, exports, module) {  return  function (it, opt) {      it = it || {};      with(it) {          var _$out_= [];          _$out_.push('
'); return _$out_.join(''); } }});

  fis3打包前和打包后的文件结构更改

  

  使用也比较简单

var tpl_rightsideBar = require('rightsideBar.tpl');tpl_rightsideBar(opt);//opt是需要传递进去的对象。详细查看rightsideBar.tpl.js的源码对应的it参数

  当然,我们封装一个组件不可能直接去使用这个tpl。而是提供一个外部组件函数,然后传递参数到这个组件函数中,组件函数不仅渲染页面(即插入组件dom),还处理相关的逻辑。如上面的rightsideBar.js就是为外部提供一个组件函数。rightsideBar组件比较简单,只需要传递一个父节点即可,不需要其他外部数据来做处理。部分源码

/** * @author chua * @date 2016-5-9 * @description 首页右侧导航栏组件,依赖模版 rightsideBar.tpl,rightsideBar.scss; * @实例化:rightsideBar = new rightsideBar(dom, datas); * @param dom {Dom} 为头部组件父级节点,将根据情况append模版,生成头部节点; * @param datas {json} 初始化组件的数据,数据格式如下 *//* * @require './rightsideBar.scss'; */var tpl_rightsideBar = require('./rightsideBar.tpl');function rightsideBar(cont,opt) {    this.cont = $(cont);    this.opt = opt;    this.init();};rightsideBar.prototype.renderHTML = function() {    //渲染前处理...    this.cont.empty().append(tpl_rightsideBar(this.opt));};rightsideBar.prototype.bindEvent = function() {    //绑定事件    this.cont.on('click', '.xxx', function() {        //处理内容...    });};rightsideBar.prototype.init = function() {    this.renderHTML();    this.bindEvent();}return rightsideBar;

  rightsideBar.js会被当做模块来编译(我们在fis-conf.js中配置的),最终编译出来后外面会被define包裹。

define('common/module/rightsideBar/rightsideBar', function(require, exports, module) {    //代码正文    ...  rightsideBar.prototype.init = function() {      this.renderHTML();      this.bindEvent();  }    return rightsideBar;});

   使用方法也比较简单

html:       
js: var rightsideBar = require('/common/module/rightsideBar/rightsideBar.js'); new rightsideBar($('.js-rightsideBar'));

 

  而我们的所有组件都放在一个组件文件夹module中,每一个组件一个文件夹(当然页可以是多个类似的组件放在一起,公用资源),文件夹下面放置所有这个组件相关的资源。如上图rightsideBar这个组件。

  那么如何做组件可视化?有几个过程是必须要做的

  1.需要遍历module中所有的组件(即遍历每一个组件下面的.js文件,一个组件文件夹下有多个js文件,表明这个组件文件夹下有多个组件,只是为了公用组件资源才放在了同一个组件下),提取出其中的使用样例(从注释代码中提取,所以必须要规定这段demo代码的规则)。

  2.必须在每一个组件的注释中写demo代码。

  3.将提取的demo代码写入指定的组件可视化文件中,随fis编译成目标文件(最终在网上打开这个文件就能预览各个组件的demo了)。

  在上面的基础上,改如何实现组价的可视化?

 

第一阶段的组件可视化

  第一阶段的组件可视化使用node+fis的方式实现。原理是在fis编译之前使用node执行一个脚本,这个脚本完成遍历组件、提取demo代码、生成组件可视化目标文件。然后在使用fis编译打包,启动服务后在网上访问即可。之所以第一阶段这么做的原因有两点:鄙人比较熟悉node但是对fis插件编写不太熟悉,不敢确定使用fis插件方式是否可行;其次上头希望能在短期内能看到一定效果。先看一下工程结构目录,v_components文件夹里包含了所有用来生成组件可视化文件的工具文件,node执行脚本为index.js

  

  工程源文件

  实现步骤:

  1.规定文件注释代码中"@example"和"@example end"之间的字符串被认为是组件demo代码。

/**   * @author chua   * @date 2016-5-9   * @description 首页右侧导航栏组件,依赖模版 rightsideBar.tpl,rightsideBar.scss;基于jQuery和jquery.cookie.js     * @实例化:rightsideBar = new rightsideBar(dom, datas);   * @param dom {Dom} 为头部组件父级节点,将根据情况append模版,生成头部节点;   * @param datas {json} 初始化组件的数据,数据格式如下     *   * @example       html:       
js: var rightsideBar = require('/common/module/rightsideBar/rightsideBar.js'); new rightsideBar($('.js-rightsideBar')); @example end */

   其中html:后面跟着的是html代码,js:后面跟着的是js执行代码。注意不要出现不符合代码格式的字符,"html:"、"js:"分别为html代码段和js代码段开始的标志。其后的代码分别要严格按照html和js的格式要求书写

  

  2.为了简化和配置更加灵活。我添加了config.json和wrap.html两个文件来配合主文件index.js文件。

  

  其中index.js文件作用是作为node脚本运行,最终生成最新的v_components.html。v_components.css和v_components.js是给v_component.html使用的,毕竟组件可视化需要一些展示和交互

  config.json的作用是希望能够配置组件的一些属性,让其更灵活,移植性更加。目前只支持一个配置:组件的目录 (建议使用相对路径,否则在index.js中可能找不到)

{    "modulePath": "../common/module/"}

  warp.html是用来生成v_components.html的模板文件。里面包含了v_components.html文件需要的样式文件和脚本文件。这个文件也是根据实际情况配置

    组件可视化    

 

  3.主程序index.js读取配置文件config.json中配置的组件目录遍历每一个组件(里面的js文件),提取注释中的demo代码,以wrap.html为模板,将html代码插入为节点,将js脚本插入到script节点中。

var fs = require('fs');...var writerStream = fs.createWriteStream('v_components.html');var regs = {    'wraphtml': /^([\s\S]*<(body)>[\s\S]*)(<\/\2>[\s\S]*)$/,    //懒惰匹配到第一个*/    'example': /\/\*\*([\s\S]*)@example[\s\S]*?html:([\s\S]*?)js:([\s\S]*?)@example end([\s|\S]*?)\*\//,//懒惰匹配第一个*/    ...};fs.readFile('config.json', function(err, data){    ...    root = obj.modulePath;    if(datas){        loopModule();    }    })fs.readFile('wrap.html', function(err, data){                            ...    datas = data.toString();    if(root){        loopModule();    }    });//遍历所有模块文件function loopModule(){    fs.readdir(root, function(err, ffiles){        ...        //遍历所有组件        ffiles.forEach(function(ffile){            ...            fs.readdir(root + ffile, function (err, files){                ...                files.forEach(function(file){
//处理每一个模块文件中的模块并找到组件主文件(js文件) if(regs.jsfile.test(file)){ ... fs.readFile(pa, function(err, data){ ... if(match = data.toString().match(regs.example)){
//匹配demo代码段 //截取相关信息并添加相关节点 ... innerRightT += '
' + match[2] + '
'; innerJs += match[3] + ";";//js脚本都放在innerJs中 count++; } if(subModLeng == 0){
//处理完所有子模块才能说明处理完了整个模块文件夹 unDomoduleLength--; } if(unDomoduleLength == 0){
//处理完所有的模块后,最后写入文件 var innerBody = warpText(innerLeftWrap, innerLeft) + warpText(innerRightWrap, warpText(innerRightTWrap, innerRightT) + warpText(innerRightBWrap, innerRightB)) + warpText(jsWrap, innerJs); //使用utf8编码写入数据 writerStream.write(datas.replace(regs.wraphtml, '$1' + innerBody + '$3'), 'UTF8'); //标记文件结尾 writerStream.end(); } }); } }) }); }) })}//用数组wrapArr包裹inner并返回包裹结果function warpText(wrapArr, inner){...}//将str字符串转换成HTML格式function transToHtml(str){...}
View Code

  最终在v_components目录下执行:node index

  生成v_components.html文件

  在pc目录下fis3编译:fis3 release dev

  在和pc同级的目录下面生成pc-dev文件夹

  在pc-dev目录下执行:node server

  打开浏览器访问:http://localhost:3000/v_components/v_components.html

  

  左侧是所有的组件的列表,点击之能看到每一个组件的展示效果。我很丑,但是我很有内涵

 

第二阶段的组件可视化——fis3插件

  之前说过要将组件可视化做成fis插件,随fis编译一起编译打包,不用在手动执行node生成相应文件。主要面临的问题是:如何让组件更加通用?这里面几个需要考虑的点

  1.如何从组件代码的注释中提取出demo代码段。

  这里我使用了下面的正则来匹配

/\/\*\*([\s\S]*)@example[\s\S]*?(html:([\s\S]*?)js:([\s\S]*?))@example end([\s|\S]*?)\*\//,//懒惰匹配第一个*/

  匹配文件注释中‘@example’和‘@example end’之间的代码。如

/**   * @example       html:       
js: var rightsideBar = require('/common/module/rightsideBar/rightsideBar.js'); new rightsideBar($('.js-rightsideBar')); @example end */

  这个部分本来想做成可以配置的,但是觉得没有太大的意义,就默认使用这个正则来匹配组件中的demo代码。

 

  2.插件需要那些参数,是的插件更加灵活

  下面是最终确定下来的参数(路径都配置绝对路径)

wrap: '/v_components/wrap.html',//组件可视化原型文件,用来包裹组件可视化代码            url: '/v_components.html', //目标文件            COMPath: '/common/module',//组件集合目录            moduleListInstead: 'instead of modules',//使用模块列表节点替换当前文本            moduleViewInstead: 'instead of view htmls',//使用模块视图列表节点替换当前文本            moduleCommentsInstead: 'instead of commnets',//使用模块注释列表节点替换当前文本            moduleJsInstead: 'instead of js'//使用js脚本节点替换当前文本

  当前文件的目录结构

  

  其中wrap对应的文件wrap.html作用非常重要。后面四个参数moduleXXXInstead对应的值必须在wrap.html中能够找到,然后使用插件拼装好的数据来替换他。wrap.html源码如下

    组件可视化    ...    
instead of modules
instead of view htmls
instead of commnets
...

   最终执行fis后上面黑色粗体文字全部被替换

    组件可视化    ...    
financialsBar
financialsSmlBar
rightsideBar
样例:
html:
      <!-- 新手 -->
      <div class="js-financialsBar1"></div>
      <!-- 活期 -->
      <div class="js-financialsBar2"></div......
...
View Code

   来自相同的组件的DOM节点的属性值data-mod相同

  fis-conf.js的配置片段

.match('::package', {        prepackager: fis.plugin('component-preview',{            wrap: '/v_components/wrap.html',//组件可视化原型文件,用来包裹组件可视化代码            url: '/v_components.html', //目标文件            COMPath: '/common/module',//组件集合目录            moduleListInstead: 'instead of modules',//使用模块列表节点替换当前文本            moduleViewInstead: 'instead of view htmls',//使用模块视图列表节点替换当前文本            moduleCommentsInstead: 'instead of commnets',//使用模块注释列表节点替换当前文本            moduleJsInstead: 'instead of js'//使用js脚本节点替换当前文本        })    })

  更详细的demo查看

  最终效果同第一阶段的组件可视化效果一样     

 

  实现原理:

  

  完整的插件源码查看

   

  如果觉得本文不错,请点击右下方【推荐】!

转载于:https://www.cnblogs.com/chuaWeb/p/component_preview.html

你可能感兴趣的文章
完成个人中心—导航标签
查看>>
matplotlib之散点图
查看>>
DML 语句
查看>>
swift------导入OC三方类找不到头文件的解决方法
查看>>
POJ 1703 Find them, Catch them (并查集)
查看>>
利用Java对本地磁盘的文件重命名
查看>>
【bzoj3648】环套树+点分治+树状数组
查看>>
折线 散点图
查看>>
小程序视图层(xx.xml)和逻辑层(xx.js)
查看>>
xml学习3
查看>>
servlet 学习笔记(三)
查看>>
在CentOS 7下更改yum源与更新系统
查看>>
POJ 2632 Crashing Robots 模拟 难度:0
查看>>
10-0-顺序表存储结构-内部排序-第10章-《数据结构》课本源码-严蔚敏吴伟民版...
查看>>
快速排序,gcc亲测能用
查看>>
An Introduction to Maximum Entropy Model
查看>>
C++ vector 排序
查看>>
SQL Server快捷方式丢了怎么启动
查看>>
0-1背包简述
查看>>
(第4天)Mybatis的最常用的开发方式
查看>>