You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用打包工具构建Vue+JSONForms单页应用时JSONForms标签页空白问题求助

不使用打包工具构建Vue+JSONForms单页应用时JSONForms标签页空白问题求助

我正在尝试不用打包工具,直接通过CDN构建一个集成JSONForms的Vue单页应用。Pre和Table标签页都能正常渲染内容,但JSONForms标签页点击后是空白的。不过如果我故意写错schema(比如把"object"改成"Abject"),页面会报错,这说明JsonForms组件应该是已经注册成功了,但就是不渲染表单内容。

我的代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue JSONForms no bundler</title>
</head>
<body>
<div id="app">
    <nav>
        <a href="#" @click.prevent="currentView = 'my_json_forms'">JSON Forms</a>
        <a href="#" @click.prevent="currentView = 'my_pre'">Pre</a>
        <a href="#" @click.prevent="currentView = 'my_table'">Table</a>
    </nav>
    <component :is="currentView"></component>
</div>

<script type="module">
    import {createApp, defineComponent} from 'https://cdn.jsdelivr.net/npm/vue/dist/vue.esm-browser.js'
    import jsonformsvue, {JsonForms} from 'https://cdn.jsdelivr.net/npm/@jsonforms/vue@3.5.1/+esm'
    import jsonformsvueVanilla, {
        vanillaRenderers
    } from 'https://cdn.jsdelivr.net/npm/@jsonforms/vue-vanilla@3.5.1/+esm';


    const MyJsonForms = defineComponent({
        components: {JsonForms},
        template: `
          <div>
            <h2>Home Page</h2>
            <p>Welcome to the home page.</p>
            <json-forms
                :data="data"
                :renderers="renderers"
                :schema="schema"
                :uischema="uischema"
                @change="onChange"
            />
          </div>`
        , data() {
            return {
                renderers: vanillaRenderers,
                schema: {
                    type: "object",
                    properties: {
                        name: {type: "string"},
                        age: {type: "integer"}
                    }
                },
                uischema: {
                    type: "VerticalLayout",
                    elements: [
                        {type: "Control", scope: "#/properties/name"},
                        {type: "Control", scope: "#/properties/age"}
                    ]
                },
                data: {name: "John", age: 30}
            }
        }, methods: {
            onChange(event) {
                this.data = event.data;
            },
        },
    });

    const MyPre = defineComponent({
        template: `
          <div>
            <h2>About Page</h2>
            <p>This is a simple Vue SPA.</p>
            <pre>{{ data }}</pre>
          </div>`, data() {
            return {
                data: {name: "John", age: 30}
            }
        }
    });

    const MyTable = defineComponent({
        template: `
          <div>
            <table>
              <thead>
              <tr>
                <th scope="col">Name</th>
                <th scope="col">Age</th>
              </tr>
              </thead>
              <tr v-for="(item,idx) in data" data-idx="{{idx}}">
                <td>{{ item.name }}</td>
                <td>{{ item.age }}</td>
              </tr>
            </table>
          </div>
        `,
        data() {
            return {
                data: [{name: "John", age: 30}]
            }
        }
    })

    createApp({
        components: {
            'my_json_forms': MyJsonForms,
            'my_pre': MyPre,
            'my_table': MyTable,
        },
        data() {
            return {
                currentView: 'home',
            };
        }
    }).mount('#app');
</script>
</body>
</html>

问题排查与解决方案

我仔细看了你的代码,找到了几个关键问题:

  • 核心问题:未安装JSONForms Vue插件
    你导入了jsonformsvue,但没有在Vue应用中调用app.use(jsonformsvue)来安装这个插件。JSONForms Vue依赖这个插件初始化内部的状态管理、核心服务等依赖项,缺少这一步的话,JsonForms组件无法完成完整的渲染流程,所以会显示空白。

  • 次要问题:初始视图指向不存在的组件
    你的应用初始currentView设为了'home',但并没有注册对应的home组件,导致页面加载时会先显示空白,虽然点击JSONForms链接能切换视图,但这个小问题可以一起修正。

  • 细节优化:动态属性绑定写法错误
    MyTable组件里的data-idx="{{idx}}"不符合Vue的动态属性绑定规范,应该改成:data-idx="idx"。

修改后的完整代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vue JSONForms no bundler</title>
</head>
<body>
<div id="app">
    <nav>
        <a href="#" @click.prevent="currentView = 'my_json_forms'">JSON Forms</a>
        <a href="#" @click.prevent="currentView = 'my_pre'">Pre</a>
        <a href="#" @click.prevent="currentView = 'my_table'">Table</a>
    </nav>
    <component :is="currentView"></component>
</div>

<script type="module">
    import {createApp, defineComponent} from 'https://cdn.jsdelivr.net/npm/vue/dist/vue.esm-browser.js'
    import jsonformsvue, {JsonForms} from 'https://cdn.jsdelivr.net/npm/@jsonforms/vue@3.5.1/+esm'
    import jsonformsvueVanilla, {
        vanillaRenderers
    } from 'https://cdn.jsdelivr.net/npm/@jsonforms/vue-vanilla@3.5.1/+esm';


    const MyJsonForms = defineComponent({
        components: {JsonForms},
        template: `
          <div>
            <h2>JSON Forms Page</h2>
            <p>Welcome to the JSON Forms page.</p>
            <json-forms
                :data="data"
                :renderers="renderers"
                :schema="schema"
                :uischema="uischema"
                @change="onChange"
            />
          </div>`
        , data() {
            return {
                renderers: vanillaRenderers,
                schema: {
                    type: "object",
                    properties: {
                        name: {type: "string"},
                        age: {type: "integer"}
                    }
                },
                uischema: {
                    type: "VerticalLayout",
                    elements: [
                        {type: "Control", scope: "#/properties/name"},
                        {type: "Control", scope: "#/properties/age"}
                    ]
                },
                data: {name: "John", age: 30}
            }
        }, methods: {
            onChange(event) {
                this.data = event.data;
            },
        },
    });

    const MyPre = defineComponent({
        template: `
          <div>
            <h2>Pre Page</h2>
            <p>This is a simple Vue SPA.</p>
            <pre>{{ data }}</pre>
          </div>`, data() {
            return {
                data: {name: "John", age: 30}
            }
        }
    });

    const MyTable = defineComponent({
        template: `
          <div>
            <h2>Table Page</h2>
            <table>
              <thead>
              <tr>
                <th scope="col">Name</th>
                <th scope="col">Age</th>
              </tr>
              </thead>
              <tr v-for="(item,idx) in data" :data-idx="idx">
                <td>{{ item.name }}</td>
                <td>{{ item.age }}</td>
              </tr>
            </table>
          </div>
        `,
        data() {
            return {
                data: [{name: "John", age: 30}]
            }
        }
    })

    const app = createApp({
        components: {
            'my_json_forms': MyJsonForms,
            'my_pre': MyPre,
            'my_table': MyTable,
        },
        data() {
            return {
                currentView: 'my_json_forms', // 修正初始视图为存在的组件
            };
        }
    })
    // 安装JSONForms Vue插件,这是核心修复点
    app.use(jsonformsvue)
    app.mount('#app');
</script>
</body>
</html>

修改后,JSONForms标签页应该就能正常渲染出包含姓名和年龄输入框的表单了,表单的数据变化也能正常同步。

备注:内容来源于stack exchange,提问作者johnmerm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 19:04:32