demand
Last time encountered a requirement that dynamic form configuration load another dynamic form configuration component, using jSON2Render has been able to achieve this function, specific implementation [dynamic interface json2Render] dynamic interface load custom template components
The children component can be placed in the corresponding slot. The children component can be placed in the corresponding slot when the children component is referenced. The children component can be placed in the corresponding slot when the children component is referenced. Implementations provide just a few simple layout components with styles to create multiple styles of components
This feature was not supported in the last version of Json2Render and has since been added
The effect
Take a look at the final result. This example is based on Vue3
The configuration of dynamic components is defined as follows
{
"fields": [{"component": "h1"."props": {
"style": { "fontSize": "40pt"}},"children": [{"component": "span"."text": "Title:" },
// Has a named slot
{ "component": "slot"."name": "header"}]}, {"component": "p"."text": "The body" },
// Default slot, and pass props to scope for children
{ "component": "slot"."props": { "attrValue": "aaaaa"}}}]Copy the code
References dynamic components and displays content in internal slots
{
"datasource": {
// Data source used to load dynamic components remotely, automatically
"template": {
"type": "fetch"."url": "/data/components/slotcmp.json"."auto": true."props": { "method": "GET"."params": {}},"defaultData": false}},"fields": [{"component": "div"."children": [{"component": "v-jrender"."condition": "$:template.data"."props": "$:template.data".// V-jrender did not support children, now supports children
"children": {
/ / the default slot
"default": [
// Use the transform expression to obtain the attrValue attribute in the scope passed by the parent
{ "component": "span"."text": "#:inner text ${scope.attrValue}"}]./ / named slot
"header": [{ "component": "span"."text": "Title slot content"}]}}]}Copy the code
The final effect is as follows
If you use the V-JRender component directly, you can add content to the children of v-jRender directly if the configuration contains a component that is slot
<script setup> import { ref } from 'vue' const fields = ref([{ component: 'div', children: [{ component: 'slot' }] }]) </script> <template> <v-jrender :fields="fields"> <! <div>content</div> </v-jrender> <template>Copy the code
The principle of
Concept of slot
Vue has a slot feature. When defining a component, you can add a slot in a location. When using the component, the children node of the component will render to the location of the defined slot
<button type="submit">
<slot></slot>
</button>
Copy the code
Slots can also be named, allowing the children node to be rendered to a location with a specific name
<div class="container">
<header>
<slot name="header"></slot>
</header>
<main>
<slot></slot>
</main>
<footer>
<slot name="footer"></slot>
</footer>
</div>
Copy the code
The vue3 runtime instance has a Slots object. Its members are a collection of methods named after the slots in the component. Each of these methods returns a VNode array of children defined in the corresponding slot
// The current object slots member
const ctx = {
slots: {
default(scope) {
/ / return vnodes
},
header(scope) {
/ / return vnodes
},
footer(scope) {
/ / return vnodes}}}Copy the code
Json2render vUe-based render extension
Json2render based vue3 implementation provides hook extension operation in each node setup link, this operation can realize the pre-processing of the node before rendering, change the node attributes according to the conditions, this process will only be performed in the first initialization process of the node, Does not affect the performance of the interface when responding to data changes
A hook is defined as follows
() = >(field, next) = > {
// Field is the definition of the current node
// We can preprocess the field property and change the property
next(field)
}
Copy the code
If you want to support slot, you need to implement a hook. The process is that the parent node performs the hook through all the children. When the component value of the child is slot, the child is identified as the slot node, and the slot node is used to display the contents of the slot. Use the name attribute of Child (default) to find the name method in slots and execute it. Replace the children element with the returned vNode set. The children element can be rendered in the slot location during rendering
about
There are a lot of things involved in the implementation of Json2Render. In the latest version, the main thing is to add dependency injection mechanism, so that it can reasonably extend the new function and share the children slots defined by all the children nodes. Specific reference project jSON2Render, net slow access to domestic mirror