The problem with vue v-model
scenario:
parent component passes a
{A: {B: "}} and a path:" A.B "
to a child component. As a base component, there will be many component references to v-model to a < input / > according to path. For example, in the current scenario, B v-model is transferred to an input
to try method and calculation attributes. However, v-model cannot hang method (in fact, it can be found in the case of pure js, but if the project built with vue-cli needs to be compiled, it is found that the compilation fails), and the calculation property cannot pass parameters, so
can not solve the problem.
=
forgive me for not describing the working hours clearly, let me change the problem description again:
parent component:
:
<son :formData="XX" :config="config"> </son>
data:{
AA:{BB:1}
DD:{EE:{FF:11}}
}
config:[
{path:AA.BB},
{path:DD.EE.FF}
]
:
<div v-for=item in config>
<input > </input> //path data
</div>
one of my problems is that I want to use the calculation attribute, but the calculation property cannot pass parameters, so it is impossible to pass in item in v-for.
subcomponents
<input v-model="value" > </input>
computed: {
value: {
get() {
return this.getVal(this.formData,this.path)
},
set(val) {
this.formData[this.path] = val;
}
}
},
methods:{
getVal(obj,key){
let subItem = this.path.split('.')
let val= JSON.parse(JSON.stringify(obj))
for(let k of subItem ){
val= val[k]
}
return val
}
}
parent component
<son :formData="XX" :path="path" > </son>
< H2 > add < / H2 >
in fact, the problem of the landlord has nothing to do with the parent-child components, which can also be accomplished by calculating properties.
<div v-for="item in myConfig">
<input v-model="item.model"></input>
</div>
myConfig:{
get(){
return this.config.map(c=>{
return {model:this.getVal(this.formData,c.path)}
})
},
set(){
//setVal
}
}
can't setter?
if you want to use the VMI model, when you change the value in the basic component, receive the value from the parent component in props, and directly use this.$emit ('input',newValue) in the basic component; you can achieve bi-directional binding
in fact, the difficulty of your requirement lies in parsing path
from formData
.
<template>
<input v-model="value"/>
</template>
<script>
export default {
props: {
formData: Object,
path: String,
},
computed: {
pathMatch() {
return this.path.match(/[^\.\[\]]+/g) || [];
},
data() {
return this.pathMatch.slice(0, this.pathMatch.length - 1).reduce((data, prop) => data && data[prop], this.formData) || {};
},
name() {
return this.pathMatch[this.pathMatch.length - 1];
},
value: {
get() {
return this.data[this.name];
},
set(val) {
this.data[this.name] = val;
this.$emit('update');
},
},
},
};
</script>
this is an interesting question, so answer it.
first of all, make sure: this is achievable.
Let me talk about the train of thought, take up a building.
- v-model is the syntax sugar of
: value
and @ input
. If it is not very clear, search directly in the vue document.
- so our goal is to implement these two functions.
if both fromData
and path
of props remain unchanged, you can directly use the getter and setter of value
.
if it is changed, simply deal with it.
{
methods: {
input (value) {
setData(this.data, this.path, value)
}
}
}
that will do. As for parseValue
and setData
methods, split
can be implemented with path, recursion, which I'll add later if necessary. This allows you to bind values more flexibly.