vue v-model 的问题

没有感情的杀手
  • 323

场景:
父组件 传一个
{A:{B:" " } }和一个 path:"A.B"
给一个子组件,子组件作为一个base组件 ,会有很多组件引用,作用是 根据path来v-model 到一个<input />,比如当前场景就是把 B v-model 到一个input
尝试了 method 和 计算属性, 但是v-model 无法挂method (实际上纯js情况下发现可以,但是使用vue-cli搭建的项目需要编译的话 发现编译不通过), 而计算属性无法传参数,
所以无法解决中情况,

==========

原谅我上班时间 描述没有描述清楚 ,我再改下问题描述:
父组件:

父组件:
<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>

我卡在一个问题是 我想要用计算属性,但是计算属性没办法传参,导致在v-for中没办法把item 传入,

回复
阅读 2.9k
4 个回答
改名字很伤神
  • 7.9k
✓ 已被采纳

子组件

<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
    }
}

父组件

<son :formData="XX" :path="path" > </son>

补充

其实楼主的问题跟父子组件没关系,同样通过计算属性就可以完成。

  <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
    }
  }

会报错 无法setter?
你如果要用v-model,在基础组件里在改变值的时候,在props里接收父组件传来的值,在基础组件里直接使用 this.$emit('input',newValue);即可实现双向绑定

其实你这个需求的难点在要从formData解析出path

<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>

这个问题挺有意思的, 所以来回答.
首先确定一下: 这个是可以实现的.
我先说下思路, 占个楼.

  1. v-model是:value@input的语法糖, 如果不是很清楚直接在vue的文档里搜.
  2. 所以我们的目的就是去实现这两个功能.

如果props的fromDatapath都不变的话, 可以直接用value的getter和setter做.
如果是变化的, 简单地处理一下.

<input :value="value" @input="input />
{
    computed: {
        value () {
            return parseValue(this.formData, this.path)
        }
    },
    methods: {
        input (value) {
            this.$emit('input', value)
        }
    }
}

这个parseValue方法, 根据两个参数获取个值, 是一定可以实现的. (具体的话分析参数2, 并递归取值) 我们之后再实现.
然后在父组件也同样处理下.

<son :formData='data' :path='path' @input='input' />

同样地,

{
    methods: {
        input (value) {
            setData(this.data, this.path, value)
        }
    }
}

这样就行啦. 至于parseValuesetData方法, split一下path, 递归就可以实现, 如果需要的话我后面补上. 这样可以做到比较灵活地绑定值了.

宣传栏