如何将我的数据存储在自定义 Vue 组件而不是根 Vue 实例中?
Posted
技术标签:
【中文标题】如何将我的数据存储在自定义 Vue 组件而不是根 Vue 实例中?【英文标题】:How do I store my data in a custom Vue component instead of the root Vue instance? 【发布时间】:2019-10-15 11:48:57 【问题描述】:我在 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”未在实例上定义,但在渲染期间被引用。通过初始化该属性,确保此属性是反应性的,无论是在数据选项中,还是对于基于类的组件。请参阅: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>
【问题讨论】:
我强烈建议看看 VueMastery 的介绍和高级组件课程。了解 v-on="$listeners" 和 v-bind="$attrs" 会对你有很大帮助。他们还深入探讨了使用槽和作用域槽的组合。最后,VueLand Discord 是获得帮助的绝佳免费资源。 【参考方案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
所做的唯一更改是在input
元素上传递v-on="$listeners"
和v-bind="$attrs"
,并删除道具中显式的“值”。
对于任何低级、可重用的 UI 组件,您都需要输入和输出数据。使用 v-model 并将数据存储在父组件中实际上是您想要做的。将数据存储在根组件中感觉很笨拙,因此通常会有中级组件。
为了证明这一点,我列出了可以高兴或悲伤的书呆子,并使用您的复选框来更新他们的状态。
在 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 组件以获得更好的体验。
【讨论】:
非常感谢您的详细回复和有趣的例子! ;-) 没问题@TiffanyDevlin-Drye!如果答案正确,请务必接受。以上是关于如何将我的数据存储在自定义 Vue 组件而不是根 Vue 实例中?的主要内容,如果未能解决你的问题,请参考以下文章