如何将 Vue VNode 渲染为字符串

2024-01-08

我正在尝试在我的 Vue 组件中使用 CSS 掩码。我需要完成实施toSvg下面的函数。这将渲染来自的 Vue VNodethis.$slots.default到 SVG 字符串。

<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>

使用示例:

<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>

显示为:


Uses Vue.extend构建一个 SVG 组件构造函数, 里面render function的构造函数,它呈现slots.default.

下一步是创建它的实例,然后mount()并获取编译后的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>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将 Vue VNode 渲染为字符串 的相关文章

  • CSS:多属性选择器

    我想设置 电子邮件 和 密码 类型的表单输入样式 但不设置其他任何样式 我正在想象类似以下的事情 input type email type password 然而 属性选择器的工作方式似乎将其解释为 输入 其中类型同时是 电子邮件 and
  • 没有嵌套容器的桌面和移动 Flexbox 布局

    我有 3 个 div 它们必须按移动布局的特定顺序排列 但我必须将第 2 个 div 作为桌面布局的侧边栏 所以对于移动设备 分区1 分区2 分区3 对于桌面 分区1 div2 分区3 在桌面布局中 div 2 有阴影背景 因此必须是父级的
  • 是否可以在没有 Javascript(仅 CSS)的情况下执行相同的操作(悬停效果)?

    我正在尝试创建一个带有图标的按钮像这样 http jsfiddle net pRdMc HTML div div class icon div span Send Email span div CSS button width 270px
  • 输入和文本字段中的背景颜色

    我想更改表单文本和输入字段中的颜色背景 但是当我这样做时 它也会影响提交按钮 是否可以通过其他不影响按钮的方式来完成 我用过这段代码 input textarea background color d1d1d1 input type tex
  • 夜间值班。单击带有文本的元素

    我遇到问题 无法单击具有某些独特文本的网页元素 我有这样的结构 div class wg wagon type title Text div 我试试这个 click wg wagon type title contains Text 但我有
  • CSS 选择器用于选择最后两个子项,而不知道列表中有多少项

    我有一个无序列表 它有时包含 4 5 6 或 7 个项目 我想知道是否有一个 CSS 选择器来选择最后两项 我意识到 last child会给我最后一件物品 是否有 倒数第二个孩子 选择器 或者 孩子数量 2 选择器 HTML ul li
  • 使用溢出时无法隐藏滚动条:auto

    我有这个CSS div background color red position relative height 414px overflow auto width 902px margin 0px auto 我尝试过overflow y
  • Symfony 2 使用 CSS 设置背景图片

    I want to put a background image for a menu in symfony But I can t figure out how to do it I managed to style a lot of t
  • vue js中的process.env.BASE_URL是什么?

    当我使用 vue cli 安装 vue 时手动选择预设 我偶然发现了 process env BASE URL 我试图在互联网上找到它 但无济于事 我找不到任何像样的解释 这是代码 const router new VueRouter mo
  • Javascript:更改输入值时设置光标位置

    当您输入公式时 我试图在我的应用程序中重现类似于 Microsoft Excel Google Sheets 的用户体验 并且您可以使用不同的公式和变量来自动完成下拉菜单 为此 在验证自动完成功能后 我希望能够控制光标的位置 例如 如果我输
  • CSS:缩放字体大小以适应父块元素的高度

    我发现的几乎每个问题和答案都谈到了视口大小 这确实不是我的问题 拿着这支笔 https codepen io njt1982 pen pZjZNM https codepen io njt1982 pen pZjZNM 我有一个非常基本的
  • 使用滤镜将css3灰色图像转为蓝色?

    我正在尝试将灰色图像变为更蓝色的色调 真的不知道如何为此设置滤镜或是否可能 该图像只有一种颜色 cacaca 其余部分透明 我正在尝试使用相同的图像进行一些叠加 以便它仅突出显示那些彩色部分而不是透明区域 一直在尝试其中的一些 但没有取得多
  • 两个 Div 之间的固定宽度间隙

    有谁知道如何修复两个 div 之间的间隙 我有一个主要内容 Div 里面有两个带有图片的 Div 视图的宽度为 768 像素 当我开始拉伸视图时 两张图片开始相互远离 但理想情况下 主要内容 Div 应该在周围有空白的情况下拉伸 并且图片之
  • 如何使用 javascript 或 jquery 生成 CSS 路径?

    关于如何生成元素的 CSS 路径有什么建议吗 CSS 路径是识别特定元素所需的 css 选择器的路径 例如 如果我的 html 是 div div class bar ul li 1 li li 2 li li span class sel
  • CSS 中的像素与像素密度

    我对 HTML 和 CSS 非常陌生 我突然想到 当决定某个东西是 5px 时 比如说 由于像素的物理尺寸取决于密度 所以 5px 在 100 ppi 的屏幕上看起来肯定比在 300 ppi 的屏幕上看起来更大ppi 这是正确的吗 如果是
  • 删除数据表列中的额外填充

    你好 我创建了 JQuery DataTables 如下所示 所以我的问题是如何删除 图片 列中过多的填充 这就是我初始化表的方式 violators tbl DataTable aoColumnDefs bSortable false a
  • 禁用引导列上的滚动

    我正在尝试禁用引导列上的滚动 这是我的代码 div class container fluid h 100 div class row h 100 div class col 4 h 100 bg dark fixed div div cl
  • 如何设置菜单按钮和菜单项的样式

    我尝试更改菜单按钮中的样式 我可以更改菜单按钮样式 但不能更改其菜单项 无论我尝试什么 菜单按钮内的菜单项都保持不变 menu button fx background color black menu button label fx ba
  • Vue:通过 CSS 选择组件的最简洁方法是什么?

    我有一个bar成分 它的使用方式如下
  • 如何将vue组件插入到contenteditable div中

    我想用 vue 创建简单的所见即所得编辑器 我发现只有一个在 vue js 上创建的真正的所见即所得编辑器 这里是 https quasar dev vue components editor 但我没有发现有插入图像的能力 其他 vue w

随机推荐