繁体   English   中英

Laravel Inertiajs:如何在服务器端或前端将生成的 Vue 字符串呈现为 Html

[英]Laravel Inertiajs: How to render a generated Vue String To Html on Server side or frontend

我已经实现了一个联系人公式,其中站点管理员可以使用基本的 laravel 和刀片模板从他的管理面板编辑整个公式。

现在我想在 inertiajs (vuejs) 中实现相同的功能。

我制作了一个工具来创建必要的 vue 代码。 所以现在我想在服务器端呈现此代码或在加载站点时动态呈现它。

我对 vue 仍然不是很熟悉,但我已经看到一些像 vue3-runtime-template 这样的库,但它们没有用。

我要呈现的代码如下所示:

<Field
    classes="transition duration-500 ease-in-out opacity-100 text-center required">
        <label>
            Was ist das Thema Ihres Anliegens?
        </label>
        <div class="grid justify-center">
            <div class="flex mt-3 flex-row items-center space-x-4">
                <Input type="radio" id="offer" name="category"
                    :value="'offer'"
                    classes="opacity-0 absolute left-1/2 peer"
                    v-model="form.category"
                />
                <Label for="offer"
                    classes="px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full"
                >
                    Fragen zum Angebot
                </Label>
            </div>
        <div class="flex mt-3 flex-row items-center space-x-4">
            <Input type="radio" id="business" name="category"
                :value="'business'"
                classes="opacity-0 absolute left-1/2 peer"
                v-model="form.category"
            />
            <Label for="business"
                classes="px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full"
            >
                Geschäftliche Anfrage
            </Label>
        </div>
        <div class="flex mt-3 flex-row items-center space-x-4">
            <Input type="radio" id="technical" name="category"
                :value="'technical'"
                classes="opacity-0 absolute left-1/2 peer"
                v-model="form.category"
            />
            <Label for="technical"
                classes="px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full"
            >
                Technische Probleme
            </Label>
        </div>
        <div class="flex mt-3 flex-row items-center space-x-4">
             <Input type="radio" id="other" name="category"
                 :value="'other'"
                 classes="opacity-0 absolute left-1/2 peer"
                 v-model="form.category"
             />
             <Label for="other"
                 classes="px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full"
             >
                 Sonstiges
             </Label>
        </div>
    </div>
</Field>

我已经尝试过的:

v-runtime-template、vue3-runtime-template、v-html 和这个。 以下方法的问题是我无法分别呈现 htmlBefore 和 htmlAfter。

<Field v-for="(children, index) in fields" :key="index"
       classes="transition duration-500 ease-in-out text-center"
       :class="index === 0 ? 'opacity-100' : 'hidden opacity-0'"
>
    <component :is="child.componentType" v-for="(child) in children" v-bind="child" />
</Field>
data() {
    return {
        fields: [
            [
                {
                    htmlBefore: '<label for="category">' +
                        '             Was ist das Thema Ihres Anliegens?' +
                        '        </label>' +
                        '        <div class="grid justify-center">' +
                        '             <div class="flex mt-3 flex-row items-center space-x-4">',
                    componentType: "Input",
                    type: "radio",
                    id: "offer",
                    name: "category",
                    value: "offer",
                    classes: "opacity-0 absolute left-1/2 peer",
                    model: this.form.category,
                },
                {
                    componentType: "Label",
                    forInput: "offer",
                    classes: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                    labelText: "Fragen zum Angebot",
                    htmlAfter: "</div>",
                },
                {
                    htmlBefore: '<div class="flex mt-3 flex-row items-center space-x-4">',
                    componentType: "Input",
                    type: 'radio',
                    id: 'business',
                    name: 'category',
                    value: "business",
                    classes: "opacity-0 absolute left-1/2 peer",
                    model: this.form.category,
                },
                {
                    componentType: "Label",
                    forInput: "business",
                    classes: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                    labelText: "Geschäftliche Anfrage",
                    htmlAfter: "</div>",
                },
                {
                    htmlBefore: '<div class="flex mt-3 flex-row items-center space-x-4">',
                    componentType: "Input",
                    type: 'radio',
                    id: 'technical',
                    name: 'category',
                    value: "technical",
                    classes: "opacity-0 absolute left-1/2 peer",
                    model: this.form.category,
                },
                {
                    componentType: "Label",
                    forInput: "technical",
                    classes: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                    labelText: "Technische Probleme",
                    htmlAfter: "</div>",
                },
                {
                    htmlBefore: '<div class="flex mt-3 flex-row items-center space-x-4">',
                    componentType: "Input",
                    type: 'radio',
                    id: 'other',
                    name: 'category',
                    value: "other",
                    classes: "opacity-0 absolute left-1/2 peer",
                    model: this.form.category,
                },
                {
                    componentType: "Label",
                    forInput: "other",
                    classes: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                    labelText: "Sonstiges",
                    htmlAfter: "</div> </div>",
                },
            ],
            [
                {
                    componentType: "Textarea",
                    classes: "w-full h-80 resize-none !text-wonder-blue mt-2 rounded-2xl placeholder-shown:border-wonder-blue",
                    name: "message",
                    minLength: 5,
                    maxLength: 5000,
                    placeholder: "Hier haben Sie genug Platz, um mir Ihr Anliegen zu schildern",
                    model: this.form.message,
                },
            ],
            [
                {
                    htmlBefore: '<div class="grid space-y-4">' +
                        '                        <div class="grid xl:grid-cols-2 xl:space-x-4 w-full">',
                    componentType: "Input",
                    name: "firstname",
                    placeholder: "Vorname*",
                    classes: "mt-4",
                    model: this.form.firstname
                },
                {
                    componentType: "Input",
                    name: "lastname",
                    placeholder: "Nachname*",
                    classes: "mt-4",
                    model: this.form.lastname,
                    htmlAfter: "</div>",
                },
                {
                    componentType: "Input",
                    isRequired: false,
                    name: "company",
                    placeholder: "Unternehmen",
                    model: this.form.company,
                },
                {
                    componentType: "Input",
                    isRequired: false,
                    name: "website",
                    placeholder: "Website",
                    model: this.form.website,
                },
                {
                    componentType: "Input",
                    isRequired: false,
                    name: "phone",
                    placeholder: "Telefonnummer",
                    model: this.form.phone,
                },
                {
                    componentType: "Input",
                    type: "email",
                    name: "email",
                    placeholder: "E-Mail Adresse*",
                    model: this.form.email,
                },
                {
                    htmlBefore: '<div class="grid xl:grid-rows-2 w-full">',
                    componentType: "Input",
                    type: "hidden",
                    name: "subscribe_newsletter",
                    model: this.form.subscribe_newsletter,
                    classes: "hidden",
                    value: 0,
                },
                {
                    htmlBefore: '<div class="flex mt-3 flex-row items-center space-x-4">',
                    componentType: "Input",
                    type: "checkbox",
                    name: "subscribe_newsletter",
                    model: this.form.subscribe_newsletter,
                    classes: "form-checkbox !px-2 !hover:ring-none",
                    value: 1,
                    isRequired: false,
                },
                {
                    componentType: "Label",
                    forInput: "subscribe_newsletter",
                    labelText: "Newsletter abonnieren",
                    htmlAfter: "</div>",
                },
                {
                    htmlBefore: '<div class="flex mt-3 flex-row items-center space-x-4">',
                    componentType: "Input",
                    type: "checkbox",
                    name: "privacy_policy",
                    model: this.form.privacy_policy,
                    classes: "form-checkbox !px-2 !hover:ring-none",
                    value: 1,
                    isRequired: false,
                },
                {
                    componentType: "Label",
                    forInput: "privacy_policy",
                    labelText: "Datenschutzerklärung zustimmen*",
                    htmlAfter: "</div> </div> </div>",
                },
            ],
        ],
    },
},

你可以在你的 vue 文件中使用v-html并将html放在那里你可以在 vue文档中看到

我已经解决了这样的问题:

//Vue 组件渲染动态创建的联系表单字段

<Field v-for="(children, index) in fields" :key="index"
       class="transition duration-500 ease-in-out text-center"
       :class="index === 0 ? 'opacity-100' : 'hidden opacity-0'"
>
    <variable-render v-for="(child) in children" v-bind="child"/>
</Field>

//要渲染的联系表单字段

fields: [
    [
        {
            componentType: "FormLabel",
            forInput: "category",
            labelText: "Was ist das Thema Ihres Anliegens?"
        },
        {
            componentType: "div",
            class: "grid justify-center",
            children: [
                {
                    componentType: "div",
                    class: "flex mt-3 flex-row items-center space-x-4",
                    children: [
                        {
                            componentType: "FormInput",
                            type: "radio",
                            id: "offer",
                            name: "category",
                            value: "offer",
                            class: "opacity-0 absolute left-1/2 peer",
                            model: this.form.category,
                        },
                        {
                            componentType: "FormLabel",
                            forInput: "offer",
                            class: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                            labelText: "Fragen zum Angebot",
                        },
                    ]
                },
                {
                    componentType: "div",
                    class: "flex mt-3 flex-row items-center space-x-4",
                    children: [
                        {
                            componentType: "FormInput",
                            type: "radio",
                            id: "business",
                            name: "category",
                            value: "business",
                            class: "opacity-0 absolute left-1/2 peer",
                            model: this.form.category,
                        },
                        {
                            componentType: "FormLabel",
                            forInput: "business",
                            class: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                            labelText: "Geschäftliche Anfrage",
                        },
                    ]
                },
                {
                    componentType: "div",
                    class: "flex mt-3 flex-row items-center space-x-4",
                    children: [
                        {
                            componentType: "FormInput",
                            type: "radio",
                            id: "technical",
                            name: "category",
                            value: "technical",
                            class: "opacity-0 absolute left-1/2 peer",
                            model: this.form.category,
                        },
                        {
                            componentType: "FormLabel",
                            forInput: "technical",
                            class: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                            labelText: "Technische Probleme",
                        },
                    ]
                },
                {
                    componentType: "div",
                    class: "flex mt-3 flex-row items-center space-x-4",
                    children: [
                        {
                            componentType: "FormInput",
                            type: "radio",
                            id: "other",
                            name: "category",
                            value: "other",
                            class: "opacity-0 absolute left-1/2 peer",
                            model: this.form.category,
                        },
                        {
                            componentType: "FormLabel",
                            forInput: "other",
                            class: "px-6 hover:cursor-pointer md:px-52 py-3 rounded-lg border border-online-blue peer-checked:text-white peer-checked:bg-wonder-blue peer-hover:text-white peer-hover:bg-wonder-blue w-full",
                            labelText: "Sonstiges",
                        },
                    ]
                },
            ]
        },
     ],
  ],

//变量渲染器.vue

<script>
import {h, resolveComponent} from 'vue';

export default {
    name: "VariableRender",

    props: {
        componentType: String,
        children: {
            type: Array,
            default: undefined
        },
    },

    methods: {
        makeVNodeTree(childObject) {
            if (Array.isArray(childObject)) {
                let childArray = [];
                for (let i = 0; i < childObject.length; i++) {
                    if (childObject[i].children !== undefined) {
                        let {componentType, children, route, makeVNodeTree, ...newChildObject} = childObject[i];
                        if(!this.tagIsValid(childObject[i].componentType)){
                            childArray.push(h(resolveComponent(childObject[i].componentType), newChildObject, this.makeVNodeTree(childObject[i].children)));
                        } else {
                            childArray.push(h(childObject[i].componentType, newChildObject, this.makeVNodeTree(childObject[i].children)));
                        }
                    } else{
                        let {componentType, route, makeVNodeTree, ...newChildObject} = childObject[i];
                        if(!this.tagIsValid(childObject[i].componentType)){
                            childArray.push(h(resolveComponent(childObject[i].componentType), newChildObject));
                        } else {
                            childArray.push(h(childObject[i].componentType, newChildObject));
                        }
                    }
                }
                return childArray;
            }
            if (childObject.children !== undefined) {
                let {children, componentType, route, makeVNodeTree, ...newChildObject} = childObject;
                if(!this.tagIsValid(childObject.componentType)){
                    return h(resolveComponent(childObject.componentType), newChildObject, this.makeVNodeTree(childObject.children));
                }
                return h(childObject.componentType, newChildObject, this.makeVNodeTree(childObject.children));
            }
            let {componentType, route, makeVNodeTree, children, ...newChildObject} = childObject;
            if(!this.tagIsValid(childObject.componentType)){
                return h(resolveComponent(childObject.componentType), newChildObject);
            }
            return h(childObject.componentType, newChildObject);
        },

        tagIsValid(tag) {
            let tagChecked = document.createElement(tag).toString();
            return tagChecked !== "[object HTMLUnknownElement]";
        }

    },

    render() {
        return this.makeVNodeTree(
            {
                componentType: this.componentType,
                children: this.children
            }
        );
    }
    ,
}
</script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM