在vue中数据的流向通常是单向的,但是实际开发中,存在父子组件都需要对父组件值进行更新的情况,vue提供了两种方法实现数据的双向绑定:
1、使用v-model指令
在父组件上 v-model 会利用子组件名为 value 的 prop 和名为 input 的事件,父组件上的值的改变通过 value 传递到子组件,子组件的改变通过 emit 触发 input 事件传递回去。
<template>
<div id="app">
<the-input v-model="name"></the-input>
<div>这是你的名字:{{ name }}</div>
</div>
</template>
<script>
import TheInput from './components/TheInput'
export default {
components: {
TheInput
},
data() {
return {
name: ''
}
},
};
</script>
子组件代码如下:
<template>
<input v-model="name" type="text">
</template>
<script>
export default {
name: 'TheInput',
props: {
value: {
require: true
}
},
computed: {
name: {
get: function () {
return this.value;
},
set: function (value) {
this.$emit('input', value)
}
},
}
}
</script>
此外,vue 组件提供了 model 属性,可以修改 v-model 在子组件中 prop 对应值和事件名,将 input 事件修改为其他事件。
<template>
<input v-model="name" type="text">
</template>
<script>
export default {
name: 'TheInput',
model: {
prop: 'pName', // 默认值为value
event: 'change' // 默认值为input
},
props: {
pName: {
require: true
}
},
computed: {
name: {
get: function () {
return this.pName;
},
set: function (value) {
this.$emit('change', value)
}
},
}
}
</script>
2、使用.sync修饰符
.sync 修饰符可以标记组件上绑定的属性为双向绑定,在子组件中可以通过 update:propName 事件子组件的值同步至父组件。
<template>
<div id="app">
<the-input :pName.sync="name"></the-input>
<div>这是你的名字:{{ name }}</div>
</div>
</template>
<script>
import TheInput from './components/TheInput'
export default {
components: {
TheInput
},
data() {
return {
name: ''
}
}
};
</script>
子组件:
<template>
<input v-model="name" type="text">
</template>
<script>
export default {
name: 'TheInput',
props: {
pName: {
require: true
}
},
computed: {
name: {
get: function () {
return this.pName;
},
set: function (value) {
this.$emit('update:pName', value)
}
},
}
}
</script>
vue提供了双向数据绑定的实现,可以方便地在父子组件两侧都更改父组件的值,但双向绑定也带来了数据更改的不确定性,不确定是父组件还是子组件更改了值。
除了使用双向绑定,是不是就没有别的方法了?答案是有的,可以通过 prop 向子组件传递一个方法,在子组件需要更改父组件值的时候,调用这个方法进行修改,同时也保证父组件值的更改只发生在父组件中,还实现双向绑定的效果。
3、单向数据绑定实现
<template>
<div id="app">
<the-input :pName.sync="name" :change="(value) => { name = value }"></the-input>
<div>这是你的名字:{{ name }}</div>
</div>
</template>
<script>
import TheInput from './components/TheInput'
export default {
components: {
TheInput
},
data() {
return {
name: '',
tempParams: {},
smsTemplate: "您的验证码是${code},将在${minutes}分钟后失效。",
}
}
};
</script>
<template>
<input v-model="name" type="text">
</template>
<script>
export default {
name: 'TheInput',
props: {
pName: {
require: true
},
change: {
type: Function,
require: true
}
},
computed: {
name: {
get: function () {
return this.pName;
},
set: function (value) {
this.change(value)
}
},
}
}
</script>