npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

jianaj-render

v1.0.5

Published

Browser rendering Library Based on virtual DOM.

Downloads

2

Readme

jianaj-render.js

基于虚拟DOM技术的浏览器端渲染库。

安装

# npm:
npm install jianaj-render
# yarn:
yarn add jianaj-render

引入和render()

import render from 'jianaj-render';

/* 
render(selector, options)
-----------------------------
渲染一个DOM元素。

@param: selector, 一个DOM元素或css3选择器。
@param: options, 包含renders['main']主方法的object配置项。
*/

render('#app', {

    // 渲染数据:

    options: {
        text: 'Hello World!'
    },
    
    // 渲染方法:

    renders: {
        main (o, w){

            // o: this.options渲染数据
            // w: this整个对象

            return ["this", {onclick: w.clickApp}, ['span', o.text]];
        }
    },

    // 其它方法:

    clickApp(){
        this._update(o => {
            o.text = 'Hello App!'
        });
    }
});

采用纯js数据表达html

// html: 
let elem = '<div></div>';
// render:
let elem = ["div"];

// html: 
let elem = '<div id="app"></div>';
// render:
let elem = ["div#app"];
let elem = ["div", {id: "app"}];

// html: 
let elem = '<div id="app" class="d-flex flex-row"></div>';
// render:
let elem = ["div#app.d-flex.flex-row"];
let elem = ["div#app.d-flex", {class: "flex-row"}];
let elem = ["div#app", {class: "d-flex flex-row"}];
let elem = ["div", {id: "app", class: "d-flex flex-row"}];

// html:
let elem = '<div id="app" class="d-flex flex-row" style="display:none;">content</div>';
// render:
let elem = ["div#app.d-flex.flex-row[style=display:none;]", "content"];
let elem = ["div#app.d-flex.flex-row", {style: "display:none;"}, "content"];
let elem = ["div", {id: "app", class: "d-flex flex-row", style: "display:none;"}, "content"];

// html:
let elem = '<div id="app"><h6>title</h6><p>text</p></div>';
// render:
let elem = ["div#app", ["h6", "title"], ["p", "text"]];
let elem = ["div#app", [
               ["h6", "title"],
               ["p", "text"]
           ]];

在渲染方法中使用 ["render[name=*]", data]

import render from 'jianaj-render';

/* 
["render[name=*]", data]
------------------------
在一个渲染方法中调用另一个渲染方法。

@attr: name, 被调用的渲染方法名称
@data: data, 传递给被调用渲染方法的参数。如果data是数组,则遍历数组调用渲染方法。
*/

render("#app", {

    options: {
        user: {
            name: "user",
            email: "[email protected]"            
        }  
    },

    renders: {
        main(o, w){
            return ["this", 
                // main方法中调用user方法    
                ["render[name=user]", o.user],

                ["div", "something else here"]
            ];
        },
        user(user, o, w){
            return ["div.user", {
                onclick: [w.clickUser, user]   
            }, [
               ["div.name", user.name],
               ["div.email", user.email]
            ]];
        }
    },
    
    clickUser(user, e, raw){       
        user.email = "[email protected]";
        // 更新
        raw.update();
    }
});

// 另一个例子, 当data是数组的时候:

render("#app", {
    options: {
        items: [
            {text: "action"},
            {text: "another action"},
            {text: "something else here"}
        ]  
    },
    renders: {
        main(o, w){
            return ["ul", [
                // o.items 是数组, item方法被遍历调用三次。
                ["render[name=item]", o.items]
            ]];
        },
        item(item, i, o, w){
            return ["li", {key: i}, ["span", item.text]];
        }
    }
});

定义组件render.widget()

import render from 'jianaj-render';

/* 
render.widget(name, options)
------------------------
定义一个组件。

@param: name, 组件名称
@param: options, 包含renders['main']主方法的object配置项。
*/

render.widget("helloworld", {
    options: {        
        text: "Hello World"    
    },
    renders: {
        main(o, w){
            return ["span", { onclick: w._click}, o.text]
        },
    },
    _click(e, raw) {
        this._update(o => {
            o.text = "Hello World";
        });
    }
});

在渲染方法中使用["widget[name=*]", data, children]

import render from 'jianaj-render';

/* 
["widget[name=*]", data, children]
------------------------
在一个渲染方法中调用组件。

@attr: name, 被调用的组件名称
@options: data, 传递给被调用组件的options。会覆盖组件默认options值。
@slots: children, 传递给被调用组件的slots,组件通过["slot[name=*]",fn]接收处理。
*/

// 定义一个helloworld组件:

render.widget("helloworld", {
    options: {        
        text: "Hello World"    
    },
    renders: {
        main(o, w){
            return ["this", {onclick: w._click}, [
                ["span", o.text],

                // 接收处理default默认插槽。
                ["slot[name=default]", (s, o, w) => {

                    // s.data = {}, s.text = "", s.children = ["p", "this is p"]

                    return s.text || s.children;
                }],

                // 接收处理demo插槽。
                ["slot[name=demo]", (s, o, w) => {

                    // s.data = {text: "demo"}, s.text = "", s.children = ["div", "demo"]

                    return s.text || s.children;
                }]            
            ]];            
        },
    },
    _click(e, raw) {
        this._update(o => {
            o.text = "Hello World";
        });
    }
});

// 调用helloworld组件:

render("#app", {
    options: {
        demo: {text: "demo"}
    },  
    renders: {
        main(o, w){
            return [  

                // 调用hello渲染方法
                ["render[name=hello]"],  
              
                ["div", "something else here"]
            ];
        },
        hello(o, w){

            // 调用helloworld组件
            return [
                "widget[name=helloworld]", 

                // options    
                {text: "hello ~"}, 

                // slots
                [ 
                    // 做为default默认插槽传给组件
                    ["p", "this is p"],
    
                    // 做为demo插槽传给组件
                    ["slot[name=demo]", o.demo, [
                        ["div", "demo"]
                    ]
                ] 
            ]];
        }
    }
});

在渲染方法中使用["slot[name=*]"]

import render from 'jianaj-render';

/* 
["slot[name=*]", data, children]
--------------------------------
调用组件的时候,向组件传递一个具名插槽。

@attr: name, 插槽名称
@data: data, 传递给插槽的数据。
@elems: children, 传递给插槽的DOM元素。
*/

render("#app", {
    options: {
        demo: {text: "demo"}
    },  
    renders: {
        main(o, w){
            return [  

                // 调用hello渲染方法
                ["render[name=hello]"],  
              
                ["div", "something else here"]
            ];
        },
        hello(o, w){

            // 调用helloworld组件
            return [
                "widget[name=helloworld]", 

                // options    
                {text: "hello ~"}, 

                // slots
                [ 
                    // 做为default默认插槽传给组件
                    ["p", "this is p"],
    
                    // 做为demo插槽传给组件
                    ["slot[name=demo]", o.demo, [
                        ["div", "demo"]
                    ]
                ] 
            ]];
        }
    }
});

/* 
["slot[name=*]", fn]
----------------------
组件对传递进来的slot做接收和处理。

@attr: name, 传递进来的slot名称, 不通过具名slot传递进来的DOM元素归到slot[name=default]。
@handler: fn, 接收slot值,处理和返回处理结果。
*/

render.widget("helloworld", {
    options: {        
        text: "Hello World"    
    },
    renders: {
        main(o, w){
            return ["this", {onclick: w.click}, [
                ["span", o.text],

                // 接收处理default默认插槽。
                ["slot[name=default]", (s, o, w) => {

                    // s.data = {}, s.text = "", s.children = ["p", "this is p"]

                    return s.text || s.children;
                }],

                // 接收处理demo插槽。
                ["slot[name=demo]", (s, o, w) => {

                    // s.data = {text: "demo"}, s.text = "", s.children = ["div", "demo"]

                    return s.text || s.children;
                }]            
            ]];            
        },
    },
    click(e, raw) {
        this._update(o => {
            o.text = "Hello World";
        });
    }
});

使用jquery

import render from 'jianaj-render';
import select2 from 'select2';

const $ = render.jquery;

render("#app", {
    renders: {
        main(o, w){
            // "this" 指代挂载元素。
            return ["this", {
                oncreate(){
                    $.ajax({
                        ...
                    }).then(res => {
                        w._update();
                    });
                }                      
            }, [
                ["div", "this is div"],
                ["select", {
                    "oncreate,onupdate,ondestroy": w.setSelect
                }]
            ]];
        }
    },
    
    setSelect(raw, rm){
        // create
        if(!rm){ 
            $(raw.node).select2({...});
        }
        // update
        else if(!$.isFunction(rm)){
            $(raw.node).select2("update", {...});
        } 
        // destroy
        else{
            $(raw.node).select2("destroy");
            rm();    
        }   
    }
});