我正在Vue中创建一个自定义复选框组件,并且可以与存储在根实例中的数据一起正常工作。我计划在多种情况下重用此组件(以及我正在构建的许多其他组件)。我不需要每次使用组件时都必须更新或编辑根Vue实例,并且只希望将数据存储在组件本身中。选中/未选中的布尔值必须是反应性的。
我尝试使用计算值,但也无法正常工作。我愿意在需要时使用它。
(此版本无效)
<body>
<script src="https://unpkg.com/vue@2.6.10"></script>
<div id="app">
<checkbox-item v-model="checkData">Active</checkbox-item>
{{ checkData }}
</div>
</body>
</html>
<script>
Vue.component('checkbox-item', {
template: `
<label class="checkbox-item">
<input type="checkbox" :checked="value"
@change="$emit('input', $event.target.checked)"
class="checkbox-input">
<span class="checkbox-label">
<slot></slot>
</span>
</label>
`,
data: function() {
return {
checkData: null
}
},
props: ['value']
})
new Vue({
el: '#app',
})
</script>
(此版本有效,但我仍然需要数据不在根实例中)
<body>
<script src="https://unpkg.com/vue@2.6.10"></script>
<div id="app">
<checkbox-item v-model="checkData">Active</checkbox-item>
{{ checkData }}
</div>
</body>
<script>
Vue.component('checkbox-item', {
template: `
<label class="checkbox-item">
<input type="checkbox" :checked="value"
@change="$emit('input', $event.target.checked)"
class="checkbox-input">
<span class="checkbox-label">
<slot></slot>
</span>
</label>
`,
props: ['value']
})
new Vue({
el: '#app',
data: {
checkData: null
}
})
</script>
我得到的错误是:
[Vue警告]:属性或方法“ checkData”未在实例上定义,但在渲染期间被引用。通过初始化属性,确保在data选项中或对于基于类的组件,此属性都是反应性的。参见:https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties。
checkData
不像在工作示例中那样被动。
编辑:好的,这是可行的!我肯定会研究使用SFC和其他代码组织方法,但目前它仍在一个html文件中。有没有人看到从长远来看这是行不通的原因?
<body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<checkbox-item></checkbox-item>
</div>
</body>
</html>
<script>
Vue.component('checkbox-item', {
template: `
<label class="checkbox-item">
<input type="checkbox" v-model="checkData"
class="checkbox-input">
<span class="checkbox-label">
<slot>Active: {{checkData}}</slot>
</span>
</label>
`,
data: function(){
return {
checkData: this.checked
}
},
})
new Vue({
el: '#app',
})
</script>
答案 0 :(得分:1)
第一个示例不起作用的原因是因为您的Vue根组件无权访问复选框的数据。
<html>
<!-- Your existing nonfunctional example -->
<body>
<script src="https://unpkg.com/vue@2.6.10"></script>
<div id="app">
<!-- Both v-model and {{ checkData }}
are asking about the root vue's checkData,
but you took that off. This is why you have an error -->
<checkbox-item v-model="checkData">Active</checkbox-item>
{{ checkData }}
</div>
</body>
</html>
在非功能示例中,当您说v-model="checkData"
时,这是在告诉父(根)Vue组件在其本地范围内找到checkData
以及v-bind:value="checkData"
和v-on:input="checkData = $event.target.value"
>
您的组件可以很好地按原样重复使用。
我对您的checkbox-item
所做的唯一更改是在v-on="$listeners"
元素上传递v-bind="$attrs"
和input
,并删除属性中的显式“值”
对于任何低级,可重用的UI组件,您都需要输入和输出数据。使用v模型并将数据存储在父组件中实际上是您想要做的。将数据存储在根组件中感觉很笨拙,因此通常存在中级组件。
为了证明这一点,我列出了一个可以高兴或难过的书呆子,并使用您的复选框更新了他们的状态。
Root Vue组件中的用法<body>
<script src="https://unpkg.com/vue@2.6.10"></script>
<div id="app">
<!-- If you wanted to take in data,
you would pass in the nerds array as a Prop
into nerd-list _from_ the root Vue instance -->
<nerd-list/>
</div>
</body>
<script>
Vue.component('nerd-list', {
template: '<div>
<h1>List of nerds and if they are happy</h1>
<div v-for="nerd in nerds" :key="nerd.id">
{{ nerd.name }}
<checkbox-item v-model="nerd.happy">Happy</checkbox-item>
</div>
</div>',
data() {
return {
nerds: [
{ name: 'Jess', happy: true, id: 1 },
{ name: 'Tiffany', happy: true, id: 2 },
]
};
},
});
Vue.component('checkbox-item', {
template: `
<label class="checkbox-item">
<input type="checkbox" :checked="value"
@change="$emit('input', $event.target.checked)"
class="checkbox-input">
<span class="checkbox-label">
<slot></slot>
</span>
</label>
`,
props: ['value']
})
new Vue({
el: '#app',
data: {}, // any data in here could be used to pass props into the nerd-list.
})
</script>
最后,如您所知,将所有这些内容都写到Javascript文件中似乎有些麻烦。我强烈建议使用Vue CLI和Vue SFC组件以获得更好的体验。