从短代码动态注入Vue 2组件

Tom*_*ler 6 vue.js vuejs2

我在管理区域中有一个表单,用户可以在其中输入包含短代码的文本:

在[temp c = 200]加热烤箱

我想要的是temp在前端显示时要解析并转换为Vue 2组件的短代码.

这是一个简化的Temperature.vue组件:

<template>
    <span class="temperature">
        {{ celsius }}&deg;C
    </span>
</template>

<script>
    import { mapGetters, mapActions } from 'vuex'

    export default {
        props: ['celsius'],
        name: 'temperature'
    }
</script>
Run Code Online (Sandbox Code Playgroud)

这是一个简化的Instructions.vue组件,它将使用短代码解析和呈现文本:

<template>
    <div v-html="parseShortcodes(text)"></div>
</template>

<script>
    import ShortcodeParser from 'meta-shortcodes'
    import Temperature from 'Temperature.vue'

    export default {

        data: () => {
            return {
                text: 'Heat oven at [temp c=200]',
                parser: ShortcodeParser()
            }
        },
        components: [
            Temperature
        ],
        methods: {
            parseShortcodes(text) {
                return this.parser.parse(text)
            }
        },
        created() {
            this.parser.add('temp', function(options) {
                return '<temperature :celsius="'+options.c+'"></temperature>'
            })
        }
    }
</script>
Run Code Online (Sandbox Code Playgroud)

解析工作正常,替换打印在前端.但<temperature>标签是字面上呈现的,而不是Vue组件,这在某种程度上是预期的.

在<温度:摄氏="200"> </温度>下加热烘箱

我似乎无法理解的是我应该采取什么步骤来实际转换为Temperature我定义的组件.它甚至可能吗?有没有更正统的方法来做到这一点,我错过了?

使用v-html渲染文本也存在安全问题.我不一定希望这个存在,但我猜测期望Temperature组件从转义字符串中出现更加牵强.我可以在插入数据库之前始终进行清理,但我仍然希望尽可能避免v-html.

Ant*_*ado 5

为了使您的示例正常工作,您需要使用Instructions组件的render函数.在渲染功能中,您可以创建一个新的Vue组件,让我们说'intruction',您将传递由短代码解析产生的字符串作为模板.在该组件声明中,您将温度组件附加为子组件,它将呈现您已通过的道具.就是这样.示例如下:

Instructions.vue

<script>
    import ShortcodeParser from 'meta-shortcodes'
    import Temperature from 'Temperature.vue'

    export default {

        data: () => {
            return {
                text: 'Heat oven at [temp c=200]',
                parser: ShortcodeParser()
            }
        },
        methods: {
            parseShortcodes(text) {
                return this.parser.parse(text)
            }
        },
        render (createElement) {

            const template = this.parseShortcodes(this.text) //returns something like this <div class="intruction">'Heat oven at <temperature :celsius="200"></temperature>'</div>

            var component = Vue.component('instruction', {
                template: template,
                components: {
                    'temperature': Temperature
                }
            })

            return createElement(
                'div',
                {
                    class: {
                        instructions: true
                    }
                },
                [
                    createElement(component)
                ]
            )
       }
    }
</script>
Run Code Online (Sandbox Code Playgroud)