我想从我的数据库中的字符串创建一个vue元素。
在这种情况下,它应该是带有笑脸表情符号的消息。
我实际上将它保存为:Some text with Emoji: :santa::skin-tone-3:
,并替换&#39; ::&#39;之间的所有有效字符串。使用<Emoji emoji=':santa::skin-tone-3:' :size='16' />
<template>
<span class=message v-html=convertedMessage></div>
</template>
<script>
import { Emoji } from 'emoji-mart-vue'
export default {
components: {
Emoji
},
computed:{
convertedMessage(){
return "Some text with Emoji: "+"<Emoji emoji=':santa::skin-tone-3:' :size='16' />"
}
}
}
</script>
但不是渲染的元素应该是这样的:
<span data-v-7f853594="" style="display: inline-block; width: 32px; height: 32px; background-image: url("https://unpkg.com/emoji-datasource-apple@4.0.4/img/apple/sheets/64.png"); background-size: 5200%; background-position: 15.6863% 41.1765%;"></span>
我只得到:
<emoji emoji=":santa::skin-tone-3:" :size="16"></emoji>
将此元素渲染为最佳可能性的最佳方式是什么?
答案 0 :(得分:2)
我现在想到的是:
convertedMessage(){
let el = Vue.compile("<Emoji emoji=':santa::skin-tone-3:' :size='16' />")
el = new Vue({
components: {
Emoji
},
render: el.render,
staticRenderFns: el.staticRenderFns
}).$mount()
return "Some text with Emoji: "+el.$el.innerHTML
}
也许还有更好的解决方案来解决这个问题?
答案 1 :(得分:1)
有些简单的方法可以完成您通常想要做的事情。如果您提供更多细节,则正确的方向可能是这些解决方案之一之前的策略模式,但是您可能想要以下解决方案之一:
1)Vue使您可以立即定义动态组件,因此这一行:
<component v-for="(component, index) in components" :key="'component'+index" :is="component.name" v-bind="component.props" />
...将在这样的对象数组中绘制一堆组件(例如):{name:'myComponentName',props:{foo:1,bar:'baz'}}。
2)Vue允许您通过简单地添加v-html =“ variable”
将HTML注入组件中例如,这是一个创建动态SVG图标的组件,其中SVG的内容是从JavaScript变量中动态注入的...
<template>
<svg xmlns="http://www.w3.org/2000/svg"
:width="width"
:height="height"
viewBox="0 0 18 18"
:aria-labelledby="name"
role="presentation"
>
<title :id="name" lang="en">{{name}} icon</title>
<g :fill="color" v-html="path">
</g>
</svg>
</template>
<script>
import icons from '../common/icons'
export default {
props: {
name: {
type: String,
default: 'box'
},
width: {
type: [Number, String],
default: 18
},
height: {
type: [Number, String],
default: 18
},
color: {
type: String,
default: 'currentColor'
}
},
data () {
return {
path: icons[this.name]
}
},
created () {
console.log(icons)
}
}
</script>
<style scoped>
svg {
display: inline-block;
vertical-align: baseline;
margin-bottom: -2px;
}
</style>
3)Vue允许您通过this。$ options.template动态定义组件模板:
export default {
props: ['name', 'props'],
template: '',
created(){
this.$options.template = `<component :is="name" ${props.join(' ')} ></component>`
},
}
4)Vue允许您定义渲染功能,因此代理组件或其他高级技巧并不重要:
Vue.component('component-proxy', {
props: {
name: {
type: String,
required: true
},
props: {
type: Object,
default: () => {}
}
},
render(h) {
// Note the h function can render anything, like h('div') works too.
// the JS object that follows can contain anything like on, class, or more elements
return h(this.name, {
attrs: this.props
});
}
});
一个聪明的天才为此在这里写了一个jsbin:http://jsbin.com/fifatod/5/edit?html,js,output
5)Vue允许您使用Vue.extend创建组件,甚至将原始JavaScript对象传递到页面或应用程序组件部分,例如这样,它从模板的简单字符串和道具数组,您还可以单独使用JS对象以相同的方式扩展数据,创建对象等。
new Vue({
el: '#app',
data: {
foo: 'bar',
props: {a: 'a', b: 'b'}
},
components: {
foo: {
template: '<p>{{ a }} {{ b }}</p>',
props: ['a', 'b']
}
}
})
答案 2 :(得分:1)
当我需要做类似的事情时,这就是我要做的事情。
我正常渲染了该组件,例如<my-component>
,但是由于我只需要渲染HTML,因此将其包裹在<div class="hidden">
中,如下所示:
<div class="hidden">
<my-component />
</div>
使用CSS:
.hidden {
display: none;
}
这样,我可以通过$refs
引用该元素,或者可以使用document.querySelector()
从DOM中获取该元素,同时使最终用户看不到它。
因此,在上面的示例中,要获取呈现的HTML,只需执行以下操作:
let el = document.querySelector('.hidden');
let renderedHTMLString = el.children[0].outerHTML;
这样,您将获得呈现的HTML,而没有与Vue.compile
或任何其他插件相关的任何间接费用。 正常渲染。把它藏起来。进入外部HTML。
答案 3 :(得分:0)
v-html
仅呈现纯HTML,请参阅https://vuejs.org/v2/guide/syntax.html#Raw-HTML
在你的情况下,你应该看一下渲染函数和JSX。我不是专家,但似乎有些人正在用dangerouslySetInnerHTML
JSX功能实现你想要的东西。看一下这个主题:How do I convert a string to jsx?
我知道有时我们别无选择,但如果你能做到最好,我认为最好的办法是避免从后端生成模板,因为它会破坏关注点(也可能是安全问题)。