How to render a Vue VNode to a String(如何将 Vue VNode 渲染为字符串)
问题描述
I'm trying to use a CSS mask in my Vue component. I need to complete the implementation of the toSvg function below. This will render the Vue VNode coming from this.$slots.default to an SVG string.
<script>
export default {
computed: {
maskImage() {
const svg = this.toSvg(this.$slots.default);
const encodedSvg = btoa(svg);
return `url('data:image/svg+xml;base64,${encodedSvg}')`;
},
},
methods: {
toSvg(vnode) {
// TODO: How can I convert the VNode to a string like the one below?
// In React, I could use const svg = ReactDOMServer.renderToStaticMarkup(vnode);
return `<svg viewBox="0 0 260 68" xmlns="http://www.w3.org/2000/svg">
<rect x="80" y="32" width="160" height="12" rx="2" />
<rect width="180" height="20" rx="2" />
<rect x="80" y="52" width="95" height="12" rx="2" />
<rect y="26" width="68" height="42" rx="2" />
</svg>`;
},
},
render(createElement) {
return createElement("div", {
attrs: {
class: "skeleton",
style: `-webkit-mask-image: ${this.maskImage}; mask-image: ${this.maskImage};`,
},
});
},
};
</script>
<style lang="scss">
.skeleton {
animation: skeleton-animation 2s infinite linear;
background: linear-gradient(to right, hsl(30, 1, 99) 0%, hsl(30, 2, 95) 30%, hsl(30, 2, 95) 70%, hsl(30, 1, 99) 100%) 0 0 / 200% 100% hsl(30, 2, 95);
overflow: hidden;
position: relative;
width: 200px;
height: 100px;
@keyframes skeleton-animation {
100% {
background-position: -200% 0;
}
}
}
</style>
Usage example:
<u-skeleton>
<svg viewBox="0 0 260 68" xmlns="http://www.w3.org/2000/svg">
<rect x="80" y="32" width="160" height="12" rx="2" />
<rect width="180" height="20" rx="2" />
<rect x="80" y="52" width="95" height="12" rx="2" />
<rect y="26" width="68" height="42" rx="2" />
</svg>
</u-skeleton>
Shows as:
Uses Vue.extend to construct one SVG component constructor, inside render function of the constructor, it renders slots.default.
Next step is create its instance, then mount() and get the compiled html.
Vue.component('v-test', {
computed: {
maskImage() {
let vnodes = this.$slots.default
let SVGConstructor = Vue.extend({
render: function (h, context) {
return h('svg', {
attrs: {
xmlns: 'http://www.w3.org/2000/svg'
}
}, vnodes)
}
})
let instance = new SVGConstructor()
instance.$mount()
const encodedSvg = btoa(instance.$el.outerHTML);
return `url('data:image/svg+xml;base64,${encodedSvg}')`;
}
},
render(createElement) {
return createElement("div", {
attrs: {
class: "skeleton",
style: `-webkit-mask-image: ${this.maskImage}; mask-image: ${this.maskImage};`,
},
})
},
})
new Vue({
el: '#app'
})
.skeleton {
animation: skeleton-animation 2s infinite linear;
background: linear-gradient(to right, #fcfcfc 0%, #f3f2f2 30%, #f3f2f2 70%, #fcfcfc 100%) 0 0 / 200% 100% #f3f2f2;
overflow: hidden;
position: relative;
width: 200px;
height: 100px;
}
@keyframes skeleton-animation {
100% {
background-position: -200% 0;
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<v-test>
<svg viewBox="0 0 260 68" xmlns="http://www.w3.org/2000/svg">
<rect x="80" y="32" width="160" height="12" rx="2" />
<rect width="180" height="20" rx="2" />
<rect x="80" y="52" width="95" height="12" rx="2" />
<rect y="26" width="68" height="42" rx="2" />
</svg>
</v-test>
<hr>
<v-test>
<svg viewBox="0 0 260 68" x="0" y="0" xmlns="http://www.w3.org/2000/svg">
<rect x="80" y="32" width="160" height="12" rx="2" />
<rect width="180" height="20" rx="2" />
<rect x="80" y="52" width="95" height="12" rx="2" />
<rect y="26" width="68" height="42" rx="2" />
</svg>
<svg viewBox="0 0 260 68" x="20" y="-20" xmlns="http://www.w3.org/2000/svg">
<rect x="80" y="32" width="160" height="12" rx="2" />
<rect width="180" height="20" rx="2" />
<rect x="80" y="52" width="95" height="12" rx="2" />
<rect y="26" width="68" height="42" rx="2" />
</svg>
</v-test>
</div>
这篇关于如何将 Vue VNode 渲染为字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何将 Vue VNode 渲染为字符串
基础教程推荐
- 即使用户允许,Gmail 也会隐藏外部电子邮件图片 2022-01-01
- 原生拖动事件后如何获取 mouseup 事件? 2022-01-01
- Bootstrap 模态出现在背景下 2022-01-01
- 检查 HTML5 拖放文件类型 2022-01-01
- fetch 是否支持原生多文件上传? 2022-01-01
- 如何添加到目前为止的天数? 2022-01-01
- Fabric JS绘制具有活动形状的多边形 2022-01-01
- Bokeh Div文本对齐 2022-01-01
- 在 contenteditable 中精确拖放 2022-01-01
- npm start 错误与 create-react-app 2022-01-01
