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

@aligov/gov-venom-render

v0.1.9

Published

dsl render

Downloads

101

Readme

政务配置化引擎 - venom dsl 渲染引擎

@aligov/gov-venom-render

venom dsl 浏览器端渲染引擎,在线体验下:地址

快速上手

有两种接入方式:

  • JIT:即在浏览器端对符合协议的 schema 数据(json 或者 jsx 格式,目前仅支持 jsx)进行实时的解析渲染的方式;
  • AOT:通过提供 webpack loader,在云端构建的方式,将符合协议的 schema 数据转化成可以执行的 js/css 代码并发布至 cdn,然后嵌到 html 中执行渲染,即对 schema 协议数据的编译解析放到了工程侧完成。

JIT

浏览器端对 schema 数据进行编译解析及页面渲染。

对此,我们统一提供了@aligov/gov-venom-render组件,用法示例可以参考demo

他是 dsl 的浏览器端渲染引擎。具体用法说明如下:

返回一个组件

import render from '@aligov/gov-venom-render';
import ReactDOM from 'react-dom';

const dsl = `
    <div>123</div>
`; // 可以放本地,也可以从后端取回

const App = render(dsl);

ReactDOM.render(<App />, mountNode);

直接渲染进 DOM

import render from '@aligov/gov-venom-render';

const dsl = `
    <div>123</div>
`; // 可以放本地,也可以从后端取回

render(dsl, {
	container: '#container',
});

目前,render 中已默认内置了以下组件:

  • State 组件:用于辅助声明可配置数据部分,他只有一个 model 属性,model 属性里可以放置你的数据操作相关的内容,他是一个对象,里面包含了三个固定的属性:
    • state: 数据声明
    • methods: 通用处理函数,目前已内置 message 方法,用于信息提示;如果放置了 init 方法在 methods 对象中,则会在页面初始化后自动执行该方法,在 UI 中通过**$store.methods.xxx()**的方式来直接调用
    • actions: 数据操作处理,可以有同步操作,也可以使用有副作用的异步请求操作,异步请求操作可以使用 es7 的 async/await;每一个 actions 里的函数,会内置:state 及 payload 两个参数,state 里有上面声明的数据项,还有 set 方法来设置数据,在使用 set 设置数据后会触发 UI 渲染;actions 里的方法通过在 UI 的表达式中以**$state.dispatch('xxx', args)**的方式来触发,payload 就是触发时传递过来的参数,这一部分的实现直接内置了轻量级的数据流管理方案roy.js,当然是可替换的,比如也可以替换为 dva 之类的
  • fusion next UI 组件,如:Button、Dialog、Input 等;
  • 部分业务组件,如:@aligov/components-table-actions 等;
  • 集团统一表单方案:Formily的表单及 UI 组件,该部分的 UI 组件不会与 next 的组件重复;
  • 集团统一 search list 组件:Alist

如果不够用,可以自己注册组件:

import React from 'react';

// 自开发组件示例
const MyComp = (props) => {
	return <div>开发者自己的组件示例 {props.name}</div>;
};

// 可以本地手动维护,也可以由后端提供,还可以在平台侧维护,平台还在开发中(手动捂脸)
const dsl = `
    <MyComp
        name='张三'
    />
`;

render(dsl, {
	components: {
		MyComp,
	},
	container: '#container',
});

组件式用法

为了进一步简化使用,我们还提供了组件式的使用方式,如:

import { Venom } from '@aligov/gov-venom-render';

const dsl = `
<>
	<State
		model={{
			methods: {

            },

            state: {
                name: '点我',
                count: 0
            },

            actions: {
                async asyncFetch(state, payload) {
                    this.methods.fetch(state);

                    this.methods.setMyName('my new name');

                    state.set({
                        name: 'hello world~'
                    });

                    setTimeout(() => {
                      this.methods.setMyName('3s change');
                    }, 3000);
                }
            }
		}}
	/>

	<>
    <button onClick={() => {
        $store.dispatch('asyncFetch');
    }}>{$state.name}</button>

    <div>{$state.count}</div>

    <TextComp />
  </>
</>
`;

const TextComp = (props) => {
	return <div>text component test</div>;
};

export default (props) => {
	return (
		<Venom
			dsl={dsl}
			init={({ methods, ...others }, ...args) => {
				console.log('init args:', args);
			}}
			components={{
				TextComp,
			}}
			methods={{
				setMyName: (myName) => {
					this.setState({ myName });
				},

				async fetch(state, payload) {
					await new Promise((resolve, reject) => {
						setTimeout(() => {
							state.set('count', 100);

							resolve();
						}, 2000);
					});
				},
			}}
		/>
	);
};

当然,也支持直接传入 url 来完成渲染,并支持 format 做格式化:

import { Venom } from '@aligov/gov-venom-render';

export default (props) => {
	return (
		<Venom
			url='https://www.fastmock.site/mock/8b5ab209e9d13691117cba3b7baea9c4/dsl/venom/dsl'
			format={(res) => res}
			init={({ methods, ...others }, ...args) => {
				console.log('init args:', args);
			}}
			methods={{
				setMyName: (myName) => {
					this.setState({ myName });
				},

				async fetch(state, payload) {
					await new Promise((resolve, reject) => {
						setTimeout(() => {
							state.set('count', 100);

							resolve();
						}, 2000);
					});
				},
			}}
		/>
	);
};

model 的两种写法

我们把渲染引擎分为了 UI 跟 Model 两部分。model 部分既可以单独维护,也可以直接存放在 DSL 中。

单独维护

// model.ts
export default {
	state: {
		name: '张三',
	},
};
// index.html
<div>{$state.name}</div>
// index.ts
import model from './model';
import dsl from 'raw-loader!./index.html'; // 什么后缀都可以,这里只是示例
import render from '@aligov/gov-venom-render';

render(dsl, model, {
	container: '#container',
});

写在 DSL 中

也可以直接将 model 写在 DSL 中,示例如下:

// index.html
<>
	<State
		model={{
			state: {
				name: '张三',
			},
		}}
	/>

	<div>{$state.name}</div>
</>
import dsl from 'raw-loader!./index.html'; // 什么后缀都可以,这里只是示例
import render from '@aligov/gov-venom-render';

render(dsl, {
	container: '#container',
});

Form 表单注册组件

表单方案我们使用的是集团统一中后台方案Formily,支持在入口方法中注册表单组件。

使用纯 DSL

纯 DSL 使用演示,适用于对 DSL 做统一管理的场景。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import render from '@aligov/gov-venom-render';

const dsl = `
<>
	<State
		model={{
			methods: {
				init({ React, formily, components, registerComponents }) {
                    const { registerFormField, createControllerBox, connect } = formily;
                    const { Checkbox } = components;

					registerFormField(
                        'custom-string',
                        connect()(props => <input {...props} value={props.value || ''} />)
                    );

					const FormLayout = createControllerBox('controller-form-layout', props => {
                        return (
                            <div>
                                {props.children}
                                {props.schema['x-component-props']['attr']}
                            </div>
                        );
                    });

                    registerComponents({FormLayout});
				}
			}
		}}
	/>

	<SchemaForm>
		<FormLayout attr='hello'>
			<Field type="custom-string" name="custom-string" title="Custom Field" />
		</FormLayout>
	</SchemaForm>
</>
`;

console.log('render:', render);

const App = render(dsl, {
	components: {},
});

ReactDOM.render(<App />, mountNode);

DSL 外注册组件

DSL 外注册组件使用演示,适用于在应用中部分使用 DSL,而非对 DSL 做统一管理。

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import render, { formily, components } from '@aligov/gov-venom-render';

const dsl = `
<SchemaForm>
    <FormLayout attr='hello'>
        <Field type="custom-string" name="custom-string" title="Custom Field" />
    </FormLayout>
</SchemaForm>
`;

const { registerFormField, createControllerBox, connect } = formily;
const { Checkbox } = components;

registerFormField(
	'custom-string',
	connect()((props) => <input {...props} value={props.value || ''} />)
);

const FormLayout = createControllerBox('controller-form-layout', (props) => {
	console.log('props:', props);

	return (
		<div>
			{props.children}
			{props.schema['x-component-props']['attr']}
		</div>
	);
});

const App = render(dsl, {
	components: {
		FormLayout,
	},
});

ReactDOM.render(<App />, mountNode);

AOT

工程侧的解析编译转换引擎,作为 webpack loader 存在,为:@aligov/gov-venom-loader

配合 build-scripts 工程构建使用,需要单独提供 build-scripts 的插件:

// build-plugin-venom.js
module.exports = async ({ onGetWebpackConfig, context }, pluginOptions = {}) => {
	onGetWebpackConfig((config) => {
		config.module
			.rule('venom')
			.test(/\.vnm$/)
			.use('@aligov/gov-venom-loader')
			.loader('@aligov/gov-venom-loader');
	});
};

然后记得在 build.json 中引入:

{
	"plugins": [
		[
			"build-plugin-fusion",
			{
				"themePackage": "@alifd/theme-design-pro"
			}
		],
		[
			"build-plugin-moment-locales",
			{
				"locales": ["zh-cn"]
			}
		],
		"@ali/build-plugin-ice-def",
		// 自定义插件
		[
			"./build-plugin-venom.js",
			{
				"forceBind": true
			}
		]
	]
}

然后就可以在项目中应用起来了,可以参考示例:gov-venom-example

TODO

[] formily 跟 alist 的注入需要统一封装实现,而不是类似现在的写死;