您的位置:首页 > 产品设计 > UI/UE

Vue 自定义组件使用v-model

2017-07-20 10:19 1031 查看
正常的业务需求中,我们需要封装一些常用的组件。现在有一个最简单的需求,封装一个有特定样式的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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: