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 条评论
登录 后参与评论

相关文章

来自专栏极客猴

详解 python3 urllib

本文是爬虫系列文章的第一篇,主要讲解 Python 3 中的 urllib 库的用法。urllib 是 Python 标准库中用于网络请求的库。该库有四个模块,...

471
来自专栏王二麻子IT技术交流园地

Oracle的Recyclebin策略

1、从oracle10g开始删除数据库表的时候并不是真正删除,而是放到了recyclebin中,这个过程类似 windows里面删除的文件会被临时放到回收站中。...

1866
来自专栏前端架构

详解location与history属性,replace,assign,

每次修改location的属性(hash除外),页面都会以新URL重新加载。 当通过上述任何一种方式修改URL之后,

751
来自专栏木子墨的前端日常

Vue-Router基础使用

作为Vue生态系统里面的一大成员,Vue-Router主要负责vue中的页面路由及其传值问题。

792
来自专栏张戈的专栏

Linux服务器的进程查看命令详解

Linux 服务器正常启动后,提供服务时会调用程序,占用进程。这时候我们如何查看系统中有哪些进程在被调用呢?我们可以通过以下命令来查看。 一、ps 命令 ps ...

7719
来自专栏phodal

Chrome 调试第三方 UI 库技巧

662
来自专栏机器学习从入门到成神

SpringMVC的JSP页面中中EL表达式不起作用的问题解决

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_35512245/articl...

881
来自专栏小狼的世界

Codeigniter中对核心类的扩展

Codeigniter框架提供了实现多个应用Application的方法,如参考资料[2]中描述的,这种方法实际上是在网站目录下存在多个入口文件和Applica...

622
来自专栏xingoo, 一个梦想做发明家的程序员

[logstash-input-http] 插件使用详解

插件介绍 Http插件是2.0版本才出现的新插件,1.x是没有这个插件的。这个插件可以帮助logstash接收其他主机或者本机发送的http报文。 插件的原理很...

2448
来自专栏不止是前端

实用主义:前端cookie介绍及操作封装

41916

扫码关注云+社区