经过研究,发现了Evan You先生的以下建议:https : //github.com/vuejs/vue/issues/7349#issuecomment-354937350
因此,我毫不犹豫地尝试了一下:
组件模板
<template>
<div v-on='{ click: dataType === `section` ? toggleSectionElements : null }'>
... magic
</div>
<template>
JS逻辑
<script>
export default {
name: `product-section`,
props: [`section`, `sectionName`, `depth`],
methods: {
toggleSectionElements() {
... magic
}
},
computed: {
dataType() {
if (this.$props.section.sections || this.$props.depth === 0) {
return `section`
} else {
return `element`
}
}
}
}
</script>
但是对于所描述的情况,在渲染过程中会导致错误:
[Vue warn]: Invalid handler for event "click": got null
有人可以建议做错了什么吗?:思维:
更新
方式Data Model
如下:
DataModel: {
mainSectionA: {
sections: {
sectionA: {
sections: {
elementA: { values: { ... } },
elementB: { values: { ... } }
}
values: { ... }
}
sectionB: {
elementA: { values: { ... } },
elementB: { values: { ... } }
}
},
values: { ... }
},
mainSectionB: {
sections: {
elementA: { values: { ... } },
elementB: { values: { ... } },
elementC: { values: { ... } },
... elements
},
values: { ... }
}
}
而不是使用三元逻辑来污染模板,您实际上应该在点击处理程序中执行检查。这不仅使您的模板更具可读性,而且由于所有逻辑都已抽象并委托给事件处理程序的回调,因此使代码维护更加容易。
因此,快速的解决方案是实际上确保toggleSectionElements()
仅当存在正确的条件时,它们才会起作用dataType
。这可以通过使用guard子句来实现:
toggleSectionElements() {
// Guard clause to prevent further code execution
if (this.dataType() !== 'section')
return;
// Magic here
}
更好的是,如果应该为每个处理程序分配单独的处理程序,则dataType
可以为此目的创建一个工厂函数:
methods: {
// This is just a factory function
toggleElements() {
switch (this.dataType()) {
case 'section':
return this.toggleSectionElements;
case 'element':
// Something else...
}
},
toggleSectionElements() {
// Magic for section element
}
}
由于将单击事件处理程序绑定到最终无能为力的元素可能会很昂贵,因此您也可以分解组件以使其更具原子性。集合元素将负责接收“部分”或“元素”的数组,并且每个“部分” /“元素”将具有其自己的组件,如下所示:
<my-collection>
,其中包含所有“ section”和“ element”组件<my-section>
组件<my-element>
组件这是VueJS真正强大的时候:您可以在内部使用动态组件<my-collection>
来确定要使用的组件,具体取决于dataType
遇到的情况。
这是v-for
通过在整个集合中运行,然后使用v-bind:is="..."
来确定特定的集合项应使用“节”还是“元素”来完成的。我知道这可能超出了您最初提出的问题的范围,但这是一个值得考虑的设计:
const collectionComponent = Vue.component('my-collection', {
template: '#my-collection-component',
data: function() {
return {
collection: [{
dataType: 'section',
description: 'Hello I am section 1'
}, {
dataType: 'element',
description: 'Hello I am element 1'
}, {
dataType: 'section',
description: 'Hello I am section 2'
}, {
dataType: 'element',
description: 'Hello I am element 2'
}]
}
},
methods: {
componentToUse(dataType) {
return 'my-' + dataType;
}
}
});
const sectionComponent = Vue.component('my-section', {
template: '#my-section-component',
props: ['itemData'],
methods: {
toggle() {
console.log('Doing some magic.');
}
}
});
const elementComponent = Vue.component('my-element', {
template: '#my-element-component',
props: ['itemData']
});
new Vue({
el: '#app'
});
.box {
border: 1px solid #999;
cursor: pointer;
margin: 10px;
padding: 10px;
}
.box:hover {
background-color: #eee;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<my-collection />
</div>
<script type="text/x-template" id="my-collection-component">
<div>
<component
v-for="(item, i) in collection"
v-bind:key="i"
v-bind:is="componentToUse(item.dataType)"
v-bind:itemData="item" />
</div>
</script>
<script type="text/x-template" id="my-section-component">
<div @click="toggle" class="box">
<h1>{{ itemData.dataType }}</h1>
<p>{{ itemData.description }}</p>
<p>Clicking on me will invoke a section-specific logic</p>
</div>
</script>
<script type="text/x-template" id="my-element-component">
<div class="box">
<h1>{{ itemData.dataType }}</h1>
<p>{{ itemData.description }}</p>
<p>Clicking on me will do nothing</p>
</div>
</script>
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句