Qjs直出实现过程

直出要做什么

在服务端为Qjs填充默认的值,例如

输入:

<div q-text="name"></div>
{"name": "Qjs"}

直出:

<div q-text="name">Qjs</div>

原理

编译阶段处理directives, 输出阶段处理filters对数据取值渲染模板获取到html

编译:

<div q-text="name">Qjs</div>
<div q-class="red: isRed"></div>

处理directives编译成underscore模板:

<div q-text="name"><%= name %></div>
<div q-class="red: isRed" class="<% if (isRed) { %>red<% } %>"></div>

输出:

处理filters, 使用模板函数对数据做渲染

实现

编译阶段虚拟dom的大框架:

编译过程基本都在cheerio建立的虚拟dom上操作, 因此解析Qjs语法等都可以直接复用Qjs的, 只需重写一套directives

q-text

var $ = require('cheerio');
directives.text = function(exp) {
    $(this.el).html('{{- __filterValue(__obj, {}) }}');
}
<div q-text="list | length"></div>

获得的模板

<div q-text="list | length"><%- __filterValue(__obj, {"arg":null,"name":"list","filters":[["length"]]}) %></div>

q-show

var $ = require('cheerio');
directives.show = function(exp) {
    $(this.el).css('__tplstrings1', 0);
}
var tpl = dom.toString().replace('__tplstrings1', '<% if (__filterValue()) { %>display:block;<% } %>');

先添加一个无用的style,之后替换成想要的

子模块:

q-vm在编译阶段只简单地植入一个变量

<div q-vm="head_module"><%= _vm[0] %></div>

在输出阶段,先获取子模块的html, 而后放入数据中渲染

var output = compiled(_.extend({}, data, {
    _vm: '<div>head_module</div>'
}});

filters异常:

filter复用浏览器端的, 但某些filter是无法正常运行的, 例如

filters.width = function(val) {
    return Match.min(val, $(window).width());
};

因此必须考虑无法兼容的问题:

function __filterValue(data, exp) {
    var root = data[exp.name];
    var name, args;
    for (var i = 0; i < exp.filters.length; i++) {
        try {
            name = exp.filters[i][0];
            args = [].concat(exp.filters[i]);
            args[0] = root;
            root = filters[name].apply(data, args);
        } catch(ex) {
            console.warn('filter failed: ' + name);
            return root;
        }
    }
    return root;
}

完整的一个例子

var fs = require('fs');
var Promise = require('promise');
// QLoader 会自动处理模块依赖关系
var QLoader = require('q-tpl/loader');

// 编译
var q = QLoader.compile({
    root: 'root',
    getQ: function(id) {
        if (id === 'root') {
            return {
                raw: [
                    '<div q-text="list | length"></div>',
                    '<div q-vm="submodule"></div>'
                ].join(''),
                filters: {
                    length: function(list) {
                        return list.length;
                    }
                },
                data: function(loader) {
                    return Promise.resolve({
                        list: [23, 3, 22]
                    });
                }
            };
        } else if (id === 'submodule') {
            return {
                raw: '<h1 q-text="text"></h1>',
                data: function(loader) {
                    return Promise.resolve({
                        text: 'hello world submodule'
                    });
                }
            };
        }
    }
});

module.exports = function(req, res) {
    // 用户请求,输出
    var loader = new Loader(req);
    q(loader).done(function(html) {
        res.write(html);
    });
};

github: [https://github.com/feix760/Q.tpl]

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏图像识别与深度学习

《HTML5实战》Lesson12

Week13  2016/12/07上午1-4节 一、复习 二、从文件系统中获取文件列表 1、forEach 详解JavaScript中的forEach()...

2825
来自专栏王磊的博客

富编译器汇总及二次开发Demo

富文本编译器汇总 名称 总大小 当前版本 官方地址 扩展方法 xhEditor 1.43 MB v1.1.14 http://xheditor.com...

3065
来自专栏小樱的经验随笔

IPython使用学习笔记

学习《利用python进行数据分析》第三章 IPython:一种交互式计算和开发环境的笔记,共享给大家,同时为自己作为备忘用。 ? 安装ipython用pip即...

2785
来自专栏程序员互动联盟

【答疑释惑】Linux下面tcsh和bash的区别

在我们的公众号里面遇到有人问tcsh和bash的区别: ? 正如小编回复的那样,这个问题其实不用太去纠结,拿到一个常用的去学习就行了。不过这里还是大致说下这两个...

2815
来自专栏程序员宝库

10 分钟理解 JS 引擎的执行机制

作者: ziwei3749 原文:https://segmentfault.com/a/1190000012806637 首先,请牢记2点: JS是单线程语言 ...

3598
来自专栏林德熙的博客

win10 uwp 资源字典 资源的key所有的元素都可以定义资源合并资源字典主题资源共享的资源用户控件资源定义

本文主要翻译ResourceDictionary and XAML resource references - UWP app developer ,里面的代码...

831
来自专栏Seebug漏洞平台

34c3 部分Web Writeup

34c3应该算是2017年年末的最后一个惊喜了,比赛题目虽然有非预期导致难度降了很多,但是从CTF中能学到什么才是最重要的,其中Web有3个XSS题目,思路非常...

42310
来自专栏守望轩

Visual Studio 2008 每日提示(二十三)

#221、在对象浏览器中按对象和成员排序 原文链接:You can sort objects and members in the Object Browse...

3676
来自专栏性能与架构

JS如何实现多线程?

单线程的问题 javascript是单线程执行的,在处理运算过程中,浏览器不能执行其它javascript脚本,UI渲染线程也会被挂起,从而导致浏览器进入僵死...

2825
来自专栏程序员的碎碎念

PHPExcel 表格导入数据代码解析(二)

前面大概讲了phpexcel用表格导入数据到数据库中的教程,今天会详细剖析函数代码,话不多说,先上代码: public function upload...

3296

扫码关注云+社区