我在管理区域中有一个表单,用户可以在其中输入包含短代码的文本:
在[temp c = 200]
加热烤箱
我想要的是temp
短代码在前端显示时被解析并转换为Vue 2组件。
这是一个简化的Temperature.vue
组件:
<template>
<span class="temperature">
{{ celsius }}°C
</span>
</template>
<script>
import { mapGetters, mapActions } from 'vuex'
export default {
props: ['celsius'],
name: 'temperature'
}
</script>
这是一个简化的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>
解析工作正常,替换打印在前端。但<temperature>
标签是字面上呈现的,而不是Vue组件,这在某种程度上是可以预料的。
加热炉温度:摄氏度=&#34; 200&#34;&gt;&lt; /温度&gt;
我无法理解的是,我应该采取哪些步骤来实际转换为我定义的Temperature
组件。它甚至可能吗?有没有更正统的方法来做到这一点,我错过了?
使用v-html
呈现文本也存在安全问题。我并不一定希望这一点存在,但是我猜测它可能更加牵强,期望Temperature
组件从转义字符串中出现。我可以在插入数据库之前始终进行清理,但我仍然希望尽可能避免使用v-html
。
答案 0 :(得分: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>
答案 1 :(得分:2)
这是我的方法,不确定它是否是你所追求的。它引入了一个动态渲染内容的中间组件。另外,我修改了Instructions.vue以进行测试,你可以修改以适合你的短代码解析器
<强> Instructions.vue 强>
<template>
<div>
<input type="text" @input="parseInput" />
<DynamicComponent :type="parsedType" :props="parsedProps"></DynamicComponent>
</div>
</template>
<script>
import DynamicComponent from './DynamicComponent';
export default {
components: {
DynamicComponent
},
data() {
return {
parsedType: '',
parsedProps: ''
};
},
methods: {
parseInput(e) { // parse the input
if (e.target.value === '[temp c=200]') { // change this to use your parser
this.parsedType = 'Temperature';
this.parsedProps = { celsius: 200 };
} else {
this.parsedType = '';
this.parsedProps = '';
}
}
}
};
</script>
<强> DynamicComponent.vue 强>
<script>
import Temperature from './Temperature';
// import all other dynamically rendered components
export default {
components: {
// let it know what components are there
Temperature
},
props: ['type', 'props'],
render(h) {
return h(this.type, {
props: this.props
}, this.$slots.default);
}
};
</script>
答案 2 :(得分:0)
目前,没有编译模板的步骤,以及它作为文本呈现的原因。我认为您可以执行以下操作以使用组件
替换文本