我是Vue的新手并试图建立一个"下拉"零件。我想从像这样的父组件中使用它:
<my-dropdown v-model="selection"></my-dropdown>
其中selection
在父项上存储为data
,应更新以反映用户的选择。要做到这一点,我相信我的下拉组件需要一个value
道具,当选择发生变化时,它需要发出input
个事件。
但是,我还想从子项本身修改value
,因为我希望能够自己使用下拉组件(我需要修改它,因为否则UI不会更新到如果组件单独使用,则反映新选择的值。
我是否可以像上面那样使用v-model
绑定,但也可以修改孩子内部的值(似乎我不能,因为value
是道具和孩子不能修改自己的道具。)
答案 0 :(得分:5)
您需要为处理输入/值值的本地值设置计算属性代理。
props: {
value: {
required: true,
}
},
computed: {
mySelection: {
get() {
return this.value;
},
set(v) {
this.$emit('input', v)
}
}
}
现在,您可以将模板设置为使用mySelection
值来管理此组件内的数据,并在更改时,正确发出数据并始终与v模型同步({{1}当你在父母身上使用它时。
答案 1 :(得分:2)
答案 2 :(得分:2)
如果要修改组件内的prop,我建议将“默认值”prop传递给组件。我就是这样做的
<MyDropdownComponent
:default="defaultValue"
:options="options"
v-model="defaultValue"
/>
然后有两种方法可供选择 -
当您使用自定义HTML时,您将无法设置所选属性。因此,您需要对您的方法充满创意。
在组件内部,您可以将默认值prop
设置为组件创建时的数据属性。您可能希望以不同方式执行此操作,而是使用watcher
。我已将其添加到下面的示例中。
export default {
...
data() {
return {
selected: '',
};
},
created() {
this.selected = this.default;
},
methods: {
// This would be fired on change of your dropdown.
// You'll have to pass the `option` as a param here,
// So that you can send that data back somehow
myChangeMethod(option) {
this.$emit('input', option);
},
},
watch: {
default() {
this.selected = this.default;
},
},
};
$emit
会将数据传递回父组件,而父组件将不会被修改。如果您使用的是标准select
元素,则无需执行此操作。
select
<template>
<select
v-if="options.length > 1"
v-model="value"
@change="myChangeMethod"
>
<option
v-for="(option, index) of options"
:key="option.name"
:value="option"
:selected="option === default"
>{{ option.name }}</option>
</select>
</template>
<script>
export default {
...
data() {
return {
value: '',
};
},
methods: {
// This would be fired on change of your dropdown
myChangeMethod() {
this.$emit('input', this.value);
},
},
};
</script>
这种方法绝对是最简单的,意味着您需要使用默认的select
元素。
答案 3 :(得分:2)
您可以使用以下模式:
演示:
'use strict';
Vue.component('prop-test', {
template: "#prop-test-template",
props: {
value: { // value is the default prop used by v-model
required: true,
type: String,
},
},
data() {
return {
dataObject: undefined,
// For testing purposes:
receiveData: true,
sendData: true,
};
},
created() {
this.dataObject = this.value;
},
watch: {
value() {
// `If` is only here for testing purposes
if(this.receiveData)
this.dataObject = this.value;
},
dataObject() {
// `If` is only here for testing purposes
if(this.sendData)
this.$emit('input', this.dataObject);
},
},
});
var app = new Vue({
el: '#app',
data: {
test: 'c',
},
});
<script src="https://unpkg.com/vue@2.0.1/dist/vue.js"></script>
<script type="text/x-template" id="prop-test-template">
<fieldset>
<select v-model="dataObject">
<option value="a">a</option>
<option value="b">b</option>
<option value="c">c</option>
<option value="d">d</option>
<option value="e">e</option>
<option value="f">f</option>
<option value="g">g</option>
<option value="h">h</option>
<option value="i">i</option>
<option value="j">j</option>
</select>
<!-- For testing purposed only: -->
<br>
<label>
<input type="checkbox" v-model="receiveData">
Receive updates
</label>
<br>
<label>
<input type="checkbox" v-model="sendData">
Send updates
</label>
<!--/ For testing purposed only: -->
</fieldset>
</script>
<div id="app">
<prop-test v-model="test"></prop-test>
<prop-test v-model="test"></prop-test>
<prop-test v-model="test"></prop-test>
</div>
请注意,此演示有一项功能,您可以关闭每个选择框的事件传播,以便您可以测试这些值是否在本地正确更新,这当然不需要生产。
答案 4 :(得分:2)
Vue的理念是:“支持,事件向上”。它甚至在文档中说明了这一点:Composing Components。
组件旨在一起使用,最常见的是 父子关系:组件A可以使用它自己的组件B. 模板。他们不可避免地需要彼此沟通: 父母可能需要将数据传递给孩子,孩子可能需要 告知父母孩子身上发生的事情。然而, 保持父母和孩子一样非常重要 通过明确定义的界面尽可能地分离。这确保了 每个组件的代码都可以相对编写和推理 隔离,从而使它们更易于维护并且可能更容易 重用。
在Vue中,父子组件关系可以概括为 支持,事件向上。父母将数据传递给孩子 道具,孩子通过事件向父母发送消息。让我们 看看他们下一步的工作方式。
不要尝试修改子组件中的值。告诉父组件有关某事的内容,如果父母关心,它可以对此做些什么。让孩子改变事物给孩子带来了太多责任。