[英]How can I abstract the following pattern? (using Vue.js)
我正在学习Vue.js。 我喜欢它很轻巧。 我正在创建一个有“设备”对象的用户界面。 每个设备都有输入和输出,可以通过mDevice.inputs或mDevice.outputs访问。 输入和输出是对象本身的列表,其中包含输入/输出名称,id和类型。
设备在屏幕上以div形式显示,并且在div上有文本“输入”和“输出”。 可以将鼠标悬停在这些标签上,并显示mDevice.inputs和mDevice.outputs。 这是那部分:
<div v-on:mouseover="device.showInputs = !device.showInputs">inputs</div>
<ul class="io-list" v-if="device.showInputs">
<li v-for="(e, idx) in device.inputs">
{{e.id}} - {{ e.the_type }}
<div
v-on:mouseover="e.showAvailableOutputs = !e.showAvailableOutputs"
class="xpull-right" style="display:inline;font-size:1.5em;">»</div>
<ul class="sub-io-list" v-if="e.showAvailableOutputs"
v-on:mouseleave="e.showAvailableOutputs = !e.showAvailableOutputs">
<li style="white-space:nowrap" v-for="io in setupOutputs">
({{io.device.model}}) - {{io.the_type}}
</li>
</ul>
</li>
</ul>
<div v-on:mouseover="device.showOutputs = !device.showOutputs">outputs</div>
<ul class="io-list" v-if="device.showOutputs">
<li v-for="(e, idx) in device.outputs">
{{e.id}} - {{ e.the_type }}
<div
v-on:mouseover="e.showAvailableInputs = !e.showAvailableInputs"
class="xpull-right" style="display:inline;font-size:1.5em;">»</div>
<ul class="sub-io-list" v-if="e.showAvailableInputs"
v-on:mouseleave="e.showAvailableInputs = !e.showAvailableInputs">
<li style="white-space:nowrap" v-for="io in setupInputs">
({{io.device.model}}) - {{io.the_type}}
</li>
</ul>
</li>
</ul>
列表是多级的(2)。 我想在这里重复一些抽象的内容。
我尝试了这个:
<template v-for="x in ['inputs','outputs']">
<div v-on:mouseover="toggleShowIOs(device,x, false)">{{x}}</div>
<ul class="io-list" v-if="showIOs(device, x, false)">
<li v-for="(e, idx) in device[x]">
{{e.id}} - {{ e.the_type }}
<div
v-on:mouseover="toggleShowIOs(e,x, true)"
class="xpull-right" style="display:inline;font-size:1.5em;">»</div>
<ul class="sub-io-list" v-if="showIOs(e,x,true)"
v-on:mouseleave="toggleShowIOs(e,x, true)">
<li style="white-space:nowrap" v-for="io in setupOutputs">
({{io.device.model}}) - {{io.the_type}}
</li>
</ul>
</li>
</ul>
</template>
但是当传递给函数toggleShowIOs时,x(天气是“输入”或“输出”)似乎并不持久。 我在想,因为我没有在vue实例的data属性中声明它。
抽象这种创建多级菜单模式的最简单方法是什么? 我在正确的轨道上吗? 我正在考虑创建一个组件。
还有另一个问题,将函数放在数据或属性中有多严重?
编辑:好的,我想我已经越来越近了。 这就是我现在所拥有的:
Vue.component('hover-menu', {
template: '#hover-menu-template',
props: ['label','menuItems'],
data : function() {
return {
show: false,
}
},
methods: {
flipAndEmit: function() {
this.show = !this.show;
this.$emit('flipAndEmit');
}
}
});
和模板:
<template id="hover-menu-template">
<div v-on:mouseover="flipAndEmit" v-on:mouseleave="flipAndEmit">
<div>{{ label }} » </div>
<ul v-if="show" style="display:inline;background-color:#5BE;">
<li is="hover-menu"
v-for="(item, index) in menuItems"
v-bind:label="item.id"
v-bind:menu-items="menuItems"></li>
</ul>
</div>
</template>
<hover-menu label="Inputs" :menu-items="device.inputs"></hover-menu>
<hover-menu label="Outputs" :menu-items="device.outputs"></hover-menu>
控件仍然很不稳定,但是我认为这是目前的答案。 一旦一切正常,我将在这里发布答案。 如果你们中有人击败我,那就更好了。
终于想通了。 我使用了Vue.js文档中的文件夹树示例来指导我。 这是模板和html:
<template id="menu-template">
<div>
<div>{{menu.name}}
<span v-if="menu.options.length > 0" v-on:mouseenter="showOptions = !showOptions">>></span>
<span v-else v-on:click="selectOption">OK</span>
</div>
<menu-children :options="menu.options" v-if="showOptions" v-on:went-out="showOptions = !showOptions"></menu-children>
</div>
</template>
<template id="menu-options-template">
<ul class="list" v-on:mouseleave="sendUp">
<li v-for="choice in options">
<amenu-parent v-if="choice.options" :menu="choice"></amenu-parent>
<span v-else>{{ choice.name }}</span>
</li>
</ul>
</template>
<div id="app">
<div v-for="r in root">
<amenu-parent :menu="r"></amenu-parent>
</div>
</div>
这是js:
Vue.component('amenu-parent', {
template: "#menu-template",
props: ['menu'],
data: function() {
return {
showOptions: false,
}
},
methods: {
selectOption: function(v) {
alert('clicked');
}
}
});
Vue.component('menu-children', {
template: "#menu-options-template",
props: ['options'],
methods: {
sendUp: function() {
this.$emit("went-out");
}
}
});
var app = new Vue({
el: "#app",
data: {
root: [{
name: 'a',
options: [{
name: '1',
options: []
}, {
name: 'asdf',
options: [{
name: 'deep',
options: []
}]
}]
}, {
name: 'number2',
options: [{
name: 'deep',
options: []
}]
}]
},
});
和一些CSS:
body {
font-size:1.8em;
}
.list > li {
background-color:#EEE;
width:300px;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.