demand

Recently met a demand, dynamic renders web interface itself is based on the configuration, page somewhere inside the slot component is a special node, the node itself will not be rendered, the user defines a component, the definition of the component in json format files, special node apply colours to a drawing gives the component after loading the configuration file, There will be multiple of these special nodes in the interface that load multiple user-defined components

Json2render is a web interface dynamic rendering library that can dynamically render the interface based on JSON data. It is a reconstructed version of the design idea of the dynamic form component vjForm. Proxy is used to rewrite the logic of expression data association relationship, separating the dependency between the transformation implementation of expression association relationship and rendering framework (VUE and React). The latest version introduces dependency injection mechanism, which makes the extension of new functions more scientific and reasonable. Vue3 is currently supported by JSON2Render

The effect

The specific effects are as follows

In this example, the main interface is dynamically rendered through JSON data. There is a place to select the component, load the JSON data of the component after selecting it, and dynamically render it to the special node area below

implementation

Json2render as a dynamic rendering component itself can also render inside Json2Render implementation nested rendering

Install @json2render/ VUE-full and element-Plus first and reference them in your project. @json2render/vue-full includes full support for VUE3

npm i @json2render/vue-full element-plus
Copy the code
import { createApp } from 'vue'
import App from './App'
import Element from 'element-plus'
import JRender from '@json2render/vue-full'
import 'element-plus/lib/theme-chalk/index.css'

createApp(App)
  .use(Element)
  .use(JRender)
  .mount('#app')
Copy the code

Implement a VUE interface, app.js

<script> import {defineComponent} from "vue" export default defineComponent({setup() {return {// Main interface configuration, Json file can be written to death or read remotely. {} } } }) </script> <template> <v-jrender :fields="config.fields" :datasource="config.datasource" :listeners="config.listeners" /> </template>Copy the code

The json data of the main interface is as follows

{
  "datasource": {
    "template": {
      Fetch data sources are used to read remote resources
      "type": "fetch".// Read the corresponding JSON file data based on the selected component name
      // Resources are stored in the /data/components directory
      "url": "#:/data/components/${model.name}.json"."auto": false."props": { "method": "GET"."params": {}},"defaultData": false}},"listeners": [{// Define a listener to rerequest custom component JSON data after the selected component name changes
      "watch": "$:model.name"."actions": [{ "handler": "@:template.request()"}}]]."fields": [{"component": "h1"."text": "Load template component"
    },
    {
      "component": "el-select"."model": "model.name"."children": [{"component": "el-option"."props": { "label": "Component 1"."value": "cmp1"}}, {"component": "el-option"."props": { "label": "The component 2"."value": "cmp2"}}, {"component": "el-option"."props": { "label": "Listening trigger"."value": "listeners"}}]}, {"component": "div"."props": {
        "style": {
          "border": "1px dashed silver"."padding": "1.25 rem." "."marginTop": "0.75 rem." "}},"children": [{"component": "p"."condition": "$:! template.data"."text": "Load custom Components"."props": { "style": { "textAlign": "center"}}}, {"component": "v-jrender"."condition": "$:template.data"."props": "$:template.data"}]}]}Copy the code

Implement three custom template components in the /data/ Components directory

cmp1.json

{
  "fields": [{ "component": "p"."text": "Paragraph text"}}]Copy the code

cmp2.json

{
  "modelValue": {},
  "fields": [{"component": "el-input"."model": "model.text" },
    { "component": "p"."text": "# : input: ${model. The text | | '}"}}]Copy the code

listeners.json

{
  "listeners": [{"watch": "$:model.on"."actions": [{"condition": "$:!!!!! model.on"."handler": "@model.value:model.value + 1"
        },
        {
          "condition": "$:! model.on"."handler": "@model.value:0"}]}, {"watch": "$:model.value"."actions": [{"condition": "$:!!!!! model.on && model.value < 100"."timeout": "$:model.num * 100"."handler": "@model.value:model.value + 1"}}]]."fields": [{"component": "el-input-number"."model": "model.num"."props": { "min": 0."max": 5}}, {"component": "el-button"."text": "Go"."props": { "onClick": "@model.on:true"}}, {"component": "el-button"."text": "Reset"."props": { "onClick": "@model.on:false"}}, {"component": "el-progress"."props": {
        "strokeWidth": 24."textInside": true."percentage": "$:model.value"}}]."modelValue": { "num": 0."value": 0}}Copy the code

See the json2Render project Templateload for an example of the code

Domestic network slow can see domestic mirror