在Vue.js中使用自定义渲染功能创建文本节点

在Vue.js中使用自定义渲染功能创建文本节点,vue.js,vuejs2,Vue.js,Vuejs2,我正在使用mylink组件根据需要围绕各种项目包装锚定标记。为此,使用了自定义的render方法-但是createElement方法只能创建HTML节点,创建纯文本节点似乎是不可能的 当前情景 my link组件的使用 结果HTML 旁注: 问题最初是针对VueJS v2.1和v2.2-beta版(2017年2月)提出的 重点是适当的语义节点(文本与元素) 创建纯文本节点的Vue。可以从呈现函数返回调用此方法以呈现纯文本字符串的结果: render(h){ return this._

我正在使用
mylink
组件根据需要围绕各种项目包装锚定标记。为此,使用了自定义的
render
方法-但是
createElement
方法只能创建HTML节点,创建纯文本节点似乎是不可能的

当前情景
my link
组件的使用 结果HTML
旁注:

  • 问题最初是针对VueJS v2.1和v2.2-beta版(2017年2月)提出的
  • 重点是适当的语义节点(文本与元素)
创建纯文本节点的Vue。可以从呈现函数返回调用此方法以呈现纯文本字符串的结果:

render(h){
    return this._v("my string value");
}
以这种方式公开它(前缀为下划线)可能表明它是一种专用API方法,因此请小心使用

如果您使用功能组件,“this”也不可用。在这种情况下,您应该调用context._v(),例如:

functional: true,
render(h, context){
    return context._v("my string value")
}

这与从窗口中提取文本(如您的注释中所示,使用“帮助”)相结合,将产生所需的结果。

组件需要根元素。在您的例子中,也许您可以使用'h4'作为根元素,因为我看到您在v-for循环中包含了它。完成此操作后,就可以创建这样的文本节点

return createElement(
    'h3',
    {},
    ['Plain text item']
);
根据Vue文档,createElement的第三个参数可以是字符串或数组,如果它是字符串,它将转换为文本节点


在Vue 2.5.x中,可以使用此选项渲染文本节点:

渲染(createElement){
返回createElement(()=>{
return document.createTextNode('Text');
});
}

通过将MyLink组件的实现更改为功能组件,您实际上可以避免使用上述答案中提到的_v方法(并可能避免使用稍后可能重命名的内部Vue方法)。功能组件不需要根元素,因此它可以绕过必须在非链接元素周围放置一个跨度的问题

MyLink的定义如下:

const MyLink = {
  functional: true,
  name: 'my-link',
  props: { url: String },
  render(createElement, context) {
    let { url } = context.props
    let slots = context.slots()
    if (url) {
      return createElement(
          'a', {
            attrs: { href: url }
          }, slots.default
      );
    }
    else {
      return slots.default 
    }
  }
};
然后,要使用它,您可以在不同的组件中执行类似的操作:

<div>
  <h4 v-for="item in items">
    <my-link :url="item.url">{{ item.text }}</my-link>
  </h4>
</div>

{{item.text}
见:


另外,作为旁注,您的原始代码片段似乎将文件命名为Link.vue。由于您正在定义自己的渲染函数,而不是使用Vue的模板系统,因此理论上,您可以将文件重命名为Link.js,删除开始和结束脚本标记,只需拥有一个完整的js组件文件。然而,若您的组件包含自定义系统(代码段并没有),那个么这种方法将不起作用。希望这能有所帮助。

实际上,这样做非常简单,不需要使用任何私有方法

仅呈现文本的
VNode
具有除文本之外的所有未定义属性

所以你可以

return { text: 'my text' };

如果您使用的是TypeScript,您可能需要断言它是一个VNode。

他们刚刚做了一些研究,最终createElement将调用document.createElement。因此,尽管可能有其他方法来完成您需要的操作,但您应该始终使用标记名,因为发送null会产生随机影响,希望帮助人员不能确定使用它是否明智,但Vue公开了一个_v方法,它是createTextVNode的别名。您可以从渲染函数中写入并返回此._v(“某些文本”)。第二个问题是确定默认插槽是否只包含文本节点,并从中提取文本@奥斯蒂奥:谢谢你在这方面的研究,我也很确定这可能会对不同的浏览器供应商产生副作用
createElement(null)
创建了一个空的VNode,但我找不到一种方法在该范围内正确包装它。@BertEvans完美
this.\u v(getChildrenTextContent(this.$slots.default))
使用类似于的文本提取方法,工作起来就像一个符咒。请考虑将此作为一个答案添加进来,注释< >代码V>()<代码>可能是内部API的一部分。谢谢@OliverHader肯定的事:)@AlainDuchesneau它在2.5中工作_v()是一个单行程序:
返回新的VNode(未定义、未定义、未定义、字符串(val))
这肯定不行。render函数应该返回一个vNode。这正是如何避免的问题-原始示例已经显示,通过使用
span
标记(这与您的
h4
建议非常类似)。这无法回答问题,还有一种方法可以通过功能组件来实现。使用功能组件绝对是一种可行的方法。这对我不起作用(v2.6.12)。
return createElement(
    'h3',
    {},
    ['Plain text item']
);
const MyLink = {
  functional: true,
  name: 'my-link',
  props: { url: String },
  render(createElement, context) {
    let { url } = context.props
    let slots = context.slots()
    if (url) {
      return createElement(
          'a', {
            attrs: { href: url }
          }, slots.default
      );
    }
    else {
      return slots.default 
    }
  }
};
<div>
  <h4 v-for="item in items">
    <my-link :url="item.url">{{ item.text }}</my-link>
  </h4>
</div>
return { text: 'my text' };