Vue js. 재귀 구성 요소가 내 인생을 망친다.
XML 파일에서 트리 뷰를 만들고 싶어서 이 작업을 수행했습니다.그러나 좀 더 유연하게 하기로 결정했을 때 몇 가지 문제가 발생했습니다.
내 컴포넌트는 다음과 같습니다.
Vue.component('elname', {
props: ['text'],
template: '<span>{{ text }}</span>'
})
Vue.component('recursive', {
props: ['d', 'liname', 'openclose'],
template: '#recursive',
data: function() {
return {
seen: true
}
}
}
)
Vue 오브젝트는 다음과 같습니다.
var appp = new Vue({
el: '#here',
data: function(){
return {
friends: '',
}
},
beforeMount() {
parser = new DOMParser();
var response = "<scope><friend><name>Alex</name><hobbies><h>music</h><h>salsa</h></hobbies></friend><friend><name>Natasha</name><hobbies><h>hiking</h></hobbies></friend></scope>";
xml = parser.parseFromString(response, 'text/xml');
children = xml.getElementsByTagName('scope')[0];
this.friends = children;
}
})
이 변수가 있습니다.seen에recursive요소
Vue.component('recursive', {
props: ['d', 'liname', 'openclose'],
template: '#recursive',
data: function() {
return {
seen: true // <-- here it is
}
}
}
)
값을 변경해야 합니다.@click이벤트: 중첩 목록을 숨기지만(JSfiddle 참조), 변경되면 값이 몇 가지 구성요소로 업데이트됩니다.
특정 컴포넌트에서만 값을 갱신하려면 어떻게 해야 합니까?
템플릿은 다음과 같습니다.
<div id="here">
<recursive :d="friends" openclose="[-]"></recursive>
</div>
<template id="recursive">
<div>
<ul v-if="d.children.length != 0">
<li v-for="n in d.childNodes" @click="seen = !seen">
<elname :text="n.tagName"></elname>
{{ openclose }}
{{seen}} <!-- it is just for testing purposes to illustrate how seen var changes -->
<recursive :d="n" openclose="[-]"></recursive>
</li>
</ul>
<ul v-else>
<elname :text="d.textContent"></elname>
</ul>
</div>
</template>
다음 두 가지 문제가 있습니다.
- 를 사용해야 합니다.
click.stop클릭 이벤트가 부모에게 전파되지 않도록 - 내부 컴포넌트가 필요합니다.
recursive토글링을 처리하다
Vue.component('elname', {
props: ['text'],
template: '<span>{{ text }}</span>'
});
Vue.component('recursive', {
props: ['d', 'openclose'],
template: '#recursive',
components: {
toggler: {
data() {
return {
seen: true
}
},
methods: {
toggle() {
this.seen = !this.seen;
}
}
}
}
});
var appp = new Vue({
el: '#here',
data: function() {
return {
friends: '',
}
},
beforeMount() {
parser = new DOMParser();
var response = "<scope><friend><name>Alex</name><hobbies><h>music</h><h>salsa</h></hobbies></friend><friend><name>Natasha</name><hobbies><h>hiking</h></hobbies></friend></scope>";
xml = parser.parseFromString(response, 'text/xml');
children = xml.getElementsByTagName('scope')[0];
this.friends = children;
}
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/2.4.2/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.min.js" integrity="sha256-Ab5a6BPGk8Sg3mpdlsHzH6khPkniIWsvEuz8Fv/s9X8=" crossorigin="anonymous"></script>
<div id="here">
<recursive :d="friends" openclose="[-]"></recursive>
</div>
<template id="recursive">
<div>
<ul v-if="d.children.length != 0">
<li is="toggler" v-for="n in d.childNodes" inline-template>
<div @click.stop="toggle">
<elname :text="n.tagName"></elname>
{{ openclose }}
<recursive v-if="seen" :d="n" openclose="[-]"></recursive>
</div>
</li>
</ul>
<ul v-else>
<elname :text="d.textContent"></elname>
</ul>
</div>
</template>
현재 1개 가지고 있습니다.seen모든 자녀 보호 상태를 제어하는 요소의 변수입니다.따라서 아무 아이나 클릭하면seen부모 값을 지정하고 이 부모의 모든 자식을 표시하거나 숨깁니다.
솔루션 1
의 유형을 변경합니다.seenvariable to array - 길이와 동일한children어레이. 핸들러를 로 변경합니다.@click="seen[i] = !seen[i]"
솔루션 2
클릭 청취자를 하위 항목으로 이동합니다.그러니깐@click="seen = !seen"템플릿에서 가장 바깥쪽에 있는 div에 전체 목록을 렌더링합니다.v-if="d.children.length && seen"
Vue.component( 'recursive-list', {
props: ["d"],
data: () => ({ expand: true }),
template: `<div style="margin: 5px">
<div v-if="Array.isArray(d)"
style="border: 1px solid black">
<button @click="expand = !expand">Show/Hide</button>
<template v-show="expand">
<recursive-list v-for="e in d" :d="e" />
</template>
<p v-show="!expand">...</p>
</div>
<p v-else>{{d}}</p>
</div>`
} )
new Vue({
el: '#main',
data: { d: ["Text", ["a","b","c"],[[1,2,3],[4,5,6],[7,8]]]
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.4.4/vue.js"></script>
<div id='main'>
<h3>List:</h3>
<recursive-list :d="d"></recursive-list>
</div>
당신의 구조를 조금 수정했습니다. 아마 당신이 필요로 하는 것은 아닐지도 모르지만, 제 생각에 더 분명해 질 것 같습니다.
<template id="tree">
<div>
<ul v-for="(tree, k, idx) in tree.childNodes">
<node :tree="tree" :idx="idx"></node>
</ul>
</div>
</template>
<template id="node">
<li>
<div v-if="tree.childNodes.length">
<span @click="seen = !seen">{{ tree.tagName }}</span>
<span>{{ seen }}</span>
<ul v-for="(node, k, id) in tree.childNodes">
<node :tree="node" :idx="id"></node>
</ul>
</div>
<div v-else>{{ tree.textContent }}</div>
</li>
</template>
https://jsfiddle.net/jonataswalker/Lw52t2dv/
언급URL : https://stackoverflow.com/questions/46403244/vue-js-recursive-component-ruins-my-life
'programing' 카테고리의 다른 글
| 정렬된 두 어레이를 정렬된 어레이로 병합하려면 어떻게 해야 합니까? (0) | 2022.08.25 |
|---|---|
| 만약 내가 스위치 경우 기본을 쓰는 게 어떨까? (0) | 2022.08.25 |
| router.push(location, onComplete?, onAbort 등)를 사용한 onComplete 및 onAbort 콜백이 있습니까? (0) | 2022.08.25 |
| 개체가 인터페이스를 구현하는지 테스트합니다. (0) | 2022.08.24 |
| html.erb 템플릿의 v-model이 함수()를 렌더링함 ({ [value code] } ) (0) | 2022.08.24 |