我有一个很大的要求。我是一名高中生,我想和朋友一起为学生创建一个应用程序。在开始时我们想使用React作为我们的反应组件,但后来我们看到了Vue,它看起来非常好。但是由于事实,我们已经有很大一部分用twig编写的应用程序,我们并不想单独使用Vue.js,因为我们必须改变很多代码,特别是我的朋友,这是在Sympfony写的后端。所以我们使用仅运行时版本,它没有模板选项,所以我必须为我们的组件编写渲染函数。而且我遇到了一个特别的问题。
我正在编写文件管理器,我需要为每个文件夹渲染图层。代码比百万字更好,所以,请看一下:
var data = {
name: 'My Tree',
children: [
{
name: 'hello',
isFolder: false,
},
{
name: 'works',
isFolder: true,
children: [
{
name: 'child2',
isFolder: true,
},
{
name: 'child3',
isFolder: false,
},
]
}
]
}
Vue.component('layer', {
render: function renderChild (createElement) {
if(data.children.length){
return createElement('ul', data.children.map(function(child){
return createElement('li', {
'class' : {
isFolder: child.isFolder,
isFile: !child.isFolder
},
attrs: {
id: "baa"
},
domProps: {
innerHTML: child.name,
},
on:{
click: function(){
console.log("yes");
},
dblclick: function(){
console.log("doubleclicked");
if(child.children.length){
// if this has children array, create whole "layer" component again.
}
}
}}
)
}))
}
},
props: {
level: {
type: Number,
required: true
},
name: {
type: String,
}
}
})
new Vue({
el: '#fileManagerContainer',
data: data,
render (h) {
return (
<layer level={1} name={"pseudo"}>
</layer>
)
}
})
我的问题是,如何编写递归调用,如果元素包含子数组,则会在doubleclick事件上呈现整个Layer组件。
提前感谢您的任何反应,建议或答案:)
答案 0 :(得分:0)
我知道这是一个非常老的问题,所以我的回答对OP不会有用,但是我想回答一下,因为我昨天遇到了同样的问题。
编写这些递归渲染函数的答案是完全不要尝试递归渲染函数本身。
对于我的示例,我有一组结构化文本(ish)-表示内容的对象数组-可以嵌套,就像这样:
[
// each array item (object) maps to an html tag
{
tag: 'h3',
classes: 'w-full md:w-4/5 lg:w-full xl:w-3/4 mx-auto font-black text-2xl lg:text-3xl',
content: 'This is a paragraph of text'
},
{
tag: 'img',
classes: 'w-2/3 md:w-1/2 xl:w-2/5 block mx-auto mt-8',
attrs: {
src: `${process.env.GLOBAL_CSS_URI}imgsrc.svg`,
alt: 'image'
}
},
{
tag: 'p',
classes: 'mt-8 text-xl w-4/5 mx-auto',
content: [
{
tag: 'strong',
content: 'This is a nested <strong> tag'
},
{
content: ' '
},
{
tag: 'a',
classes: 'underline ml-2',
content: 'This is a link within a <p> tag',
attrs: {
href: '#'
}
},
{
content: '.'
}
]
}
]
请注意嵌套元素-这些元素需要递归才能正确呈现。
解决方案是将 actual 渲染工作移至以下方法:
export default {
name: 'block',
props: {
block: {
type: Object,
required: true
}
},
methods: {
renderBlock (h, block) {
// handle plain text without a tag
if (!block.tag) return this._v(block.content || '')
if (Array.isArray(block.content)) {
return h(block.tag, { class: block.classes }, block.content.map(childBlock => this.renderBlock(h, childBlock)))
}
// return an html tag with classes attached and content inside
return h(block.tag, { class: block.classes, attrs: block.attrs, on: block.on }, block.content)
}
},
render: function(h) {
return this.renderBlock(h, this.block)
}
}
因此render函数将调用renderBlock
方法,而renderBlock
方法将在需要时反复调用自身-递归发生在方法调用内。您将看到该方法可以检查content
属性是否为Array
类型-此时,它执行相同的渲染任务,但没有按原样传递内容,它将其作为Array映射传递,为数组中的每个项目调用相同的render方法。
这意味着,无论嵌套的内容有多深,它都将继续调用自身,直到到达栈的“底部”为止。
我希望这可以帮助将来节省一些时间-我当然希望我昨天能有这样的一个例子-我会为自己节省几个小时!