我想在Vue.js 2.3中对我的表单输入进行双向数据绑定。但是,我不能使用v-model
指令,因为我希望仅在单击提交按钮时才更新数据。同时,输入值可以从另一个Vue方法更新,因此它应该绑定到数据属性text
。我编造了类似jsFiddle的内容:
<div id="demo">
<input :value="text" ref="input">
<button @click="update">OK</button>
<p id="result">{{text}}</p>
</div>
new Vue({
el: '#demo',
data: function() {
return {
text: ''
};
},
methods: {
update: function () {
this.text = this.$refs.input.value;
}
}
});
它有效,但当有更多输入时它不能很好地扩展。有没有更简单的方法来实现这一点,而不使用$ refs?
答案 0 :(得分:2)
您可以使用对象并将其属性绑定到输入。然后,在update
方法中,您可以将属性复制到另一个对象以进行显示。然后,您可以设置深度观察器,以便在对象更改时更新输入的值。复制属性时,您需要使用this.$set
,以便更改将在Vue中注册。
new Vue({
el: '#demo',
data: function() {
return {
inputVals: {
text: '',
number: 0
},
displayVals: {}
};
},
methods: {
update() {
this.copyObject(this.displayVals, this.inputVals);
},
copyObject(toSet, toGet) {
Object.keys(toGet).forEach((key) => {
this.$set(toSet, key, toGet[key]);
});
}
},
watch: {
displayVals: {
deep: true,
handler() {
this.copyObject(this.inputVals, this.displayVals);
}
}
}
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="demo">
<input v-model="inputVals.text">
<input v-model="inputVals.number">
<button @click="update">OK</button>
<input v-for="val, key in displayVals" v-model="displayVals[key]">
</div>
&#13;
如果你正在使用ES2015,你可以直接复制对象,所以这不是详细的:
new Vue({
el: '#demo',
data() {
return {
inputVals: { text: '', number: 0 },
displayVals: {}
};
},
methods: {
update() {
this.displayVals = {...this.inputVals};
},
},
watch: {
displayVals: {
deep: true,
handler() {
this.inputVals = {...this.displayVals};
}
}
}
})
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.3.4/vue.min.js"></script>
<div id="demo">
<input v-model="inputVals.text">
<input v-model="inputVals.number">
<button @click="update">OK</button>
<input v-for="val, key in displayVals" v-model="displayVals[key]">
</div>
&#13;
答案 1 :(得分:1)
您可以使用两个单独的数据属性,一个用于<input>
的值,另一个用于单击“确定”按钮后提交的值。
<div id="demo">
<input v-model="editText">
<button @click="update">OK</button>
<p id="result">{{text}}</p>
</div>
new Vue({
el: '#demo',
data: function() {
return {
editText: '',
text: ''
};
},
methods: {
update: function () {
this.text = this.editText;
}
}
});
答案 2 :(得分:1)
与其他答案略有不同,我认为你可以实现轻松扩展的方法。
这是第一次传递,但是使用组件,您可以构建自己的输入元素,并在需要时精确提交。下面是一个输入元素的示例,当它位于t-form
组件之外时,它就像常规输入元素一样工作,但只在v-model
内submit
上更新t-form
Vue.component("t-input", {
props:["value"],
template:`
<input type="text" v-model="internalValue" @input="onInput">
`,
data(){
return {
internalValue: this.value,
wrapped: false
}
},
watch:{
value(newVal){
this.internalValue = newVal
}
},
methods:{
update(){
this.$emit('input', this.internalValue)
},
onInput(){
if (!this.wrapped)
this.$emit('input', this.internalValue)
}
},
mounted(){
if(this.$parent.isTriggeredForm){
this.$parent.register(this)
this.wrapped = true
}
}
})
以下是t-form
。
Vue.component("t-form",{
template:`
<form @submit.prevent="submit">
<slot></slot>
</form>
`,
data(){
return {
isTriggeredForm: true,
inputs:[]
}
},
methods:{
submit(){
for(let input of this.inputs)
input.update()
},
register(input){
this.inputs.push(input)
}
}
})
有了这些,你的工作变得非常简单。
<t-form>
<t-input v-model="text"></t-input><br>
<t-input v-model="text2"></t-input><br>
<t-input v-model="text3"></t-input><br>
<t-input v-model="text4"></t-input><br>
<button>Submit</button>
</t-form>
此模板仅在单击按钮时更新绑定的表达式。您可以拥有任意数量的t-inputs
。
这是一个工作示例。我在表单内部和外部都包含了t-input
元素,因此您可以在表单内部看到模型仅在提交时更新,而在表单外部,元素的工作方式与典型输入相同。
console.clear()
//
Vue.component("t-input", {
props: ["value"],
template: `
<input type="text" v-model="internalValue" @input="onInput">
`,
data() {
return {
internalValue: this.value,
wrapped: false
}
},
watch: {
value(newVal) {
this.internalValue = newVal
}
},
methods: {
update() {
this.$emit('input', this.internalValue)
},
onInput() {
if (!this.wrapped)
this.$emit('input', this.internalValue)
}
},
mounted() {
if (this.$parent.isTriggeredForm) {
this.$parent.register(this)
this.wrapped = true
}
}
})
Vue.component("t-form", {
template: `
<form @submit.prevent="submit">
<slot></slot>
</form>
`,
data() {
return {
isTriggeredForm: true,
inputs: []
}
},
methods: {
submit() {
for (let input of this.inputs)
input.update()
},
register(input) {
this.inputs.push(input)
}
}
})
new Vue({
el: "#app",
data: {
text: "bob",
text2: "mary",
text3: "jane",
text4: "billy"
},
})
&#13;
<script src="https://unpkg.com/vue@2.2.6/dist/vue.js"></script>
<div id="app">
<t-form>
<t-input v-model="text"></t-input><br>
<t-input v-model="text2"></t-input><br>
<t-input v-model="text3"></t-input><br>
<t-input v-model="text4"></t-input><br>
<button>Submit</button>
</t-form>
Non-wrapped:
<t-input v-model="text"></t-input>
<h4>Data</h4>
{{$data}}
<h4>Update Data</h4>
<button type="button" @click="text='jerome'">Change Text</button>
</div>
&#13;