Vue 自定义组件使用v-model
正常的业务需求中,我们需要封装一些常用的组件。现在有一个最简单的需求,封装一个有特定样式的input框,够简单吧?好,我们来这样封装:字符串模板文件命名为 CInput.vue: <template><input type="text" class="your-custom-class-name" v-model="name" ></template><style lang="
正常的业务需求中,我们需要封装一些常用的组件。现在有一个最简单的需求,封装一个有特定样式的input框,够简单吧? 好,我们来这样封装:
字符串模板文件命名为 CInput.vue:
<template>
<input type="text" class="your-custom-class-name" v-model="name" >
</template>
<style lang="scss">
.your-custom-class-name {
...
}
</style>
<script>
export default {
props: {
name: String
}
}
</script>
ok,我们在父组件中引用此组件,父组件的data函数长这样:
data () {
return {
name: null,
... //other data
}
}
父组件里面引用子组件的代码长这样:
加载页面,ok,完全正常,但是我们在输入框体里面输入值,修改name的值的时候:
会出现警告:
警告的意思是说,不应该直接将父元素传递给子元素的属性直接挂在到子组件上面【双向绑定】。应该在子组件的data或者计算属性里面基于这个属性来初始化数据。 参考资料:单向数据流
当父组件的属性变化时,将传导给子组件,但是不会反过来。这是为了防止子组件无意修改了父组件的状态——这会让应用的数据流难以理解。
子组件修改父组件数据,最好是通过 eventHub or vuex来实现。当然特定场景使用简单粗暴的this.$parent.xx来修改吧。
回到正题,现在这样来做是肯定不行的,所以后来,我瞎X尝试***【当然这个方法本身是不可取的,请不要采用这个办法】***,将父组件中的name的值,默认设置为一个对象,而不是null.
代码长这样
data () {
return {
name: { value: null }
}
}
然后将子组件的v-model不是绑定name 而是绑定name.value,代码长这样:
<input type="text" class="your-custom-class-name" v-model="name.value" >
这样我们在界面上修改值的时候,就不会报警告了。【我们拿错误的实验得到了正确的结果】。 实际上可以点击上面关于单向数据流的链接,可以知道,不应该直接改变父组件的数据,项目复杂度上去之后,难以维护,你根本不知道是谁改变了父组件里面的数据。但是特定场景是需要直接修改父元素的数据,请使用.sync修饰符
然而为什么不用v-model来用于我们自己的组件呢,v-model对数据进行双向绑定实际上是一个语法糖。比如我们对于一个input实现双向绑定。
代码长这样:
<input v-model="data">
实际上是语法糖:
<input
v-bind:value="data"
v-on:input="data = $event.target.value">
input上有一个Input事件,值变化的时候,会将值绑定给这个变量data。
在vue版本2.2.0之后,v-model可以配置:
1,组件定一个属性 value
2, 在有新的值触发或者说值发生变化时,触发input事件 like this:
this.$emit('input', newValue)
好,现在我们来修改上面的代码:
<template>
<input type="text" :value="currentValue" @input="handleInput">
</template>
<script>
export default {
data () {
return {
currentValue: this.value //不直接绑定prop,而是在data 或者 computed 里面根据prop初始化自己领域的值
}
},
props: {
value: [String, Number] // key code
},
methods: {
handleInput() {
const value = event.target.value
this.currentValue = value
this.$emit('input', value) // key code
}
}
}
</script>
binggo! 这样的话,就不会有⚠️了
//父元素的data长这样
data () {
return {
name: null,
... //other data
}
}
//引用子组件
<c-input v-model="name"> </c-input>
这样也不会报错了!
当然如果子组件里面还有 第三层其他的自定义组件(父亲->子组件->孙子组件),你可能需要监听在子组件里面的v-model=“data” 的data值,使用watch
,如果这个值发生了变化,调用 this.$emit('input', newValue)
。
更多推荐
所有评论(0)