在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月)提出的
- 重点是适当的语义节点(文本与元素)
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' };