prop 的 sync 修饰符与自定义指令 v-model
prop 的 sync 修饰符
允许我们通过 prop 进行双向数据绑定而不触发子组件修改 props 的警告
使用方式如下
子组件 Nam.vue
props:{
name:{
defalut:'x',
type:String
}
}
methods:{
changeName(){
this.$emit(update:name,somevalue)// Tip:update字段是必须的,后面跟你需要改变的prop名称
}
}
父组件
<Name :name.sync="name"></Name>
<!--严格要求书写格式-->
export defalut { name:'s' watch:{ 's':function(newValue,oldValue){
console.log('新的名字'+newValue) } } }
如果你已经开始使用 TS 语法,并用到了vue-property-decorator这个库,那么你可以像下面这样实现prop. sync
子组件 Name.vue
说明:
@PropSync
装饰器与@prop
用法类似,二者的区别在于:
@PropSync
装饰器接收两个参数propName: string
表示父组件传递过来的属性名options: Constructor | Constructor[] | PropOptions
与@Prop
的第一个参数一致@PropSync
会生成一个新的计算属性
import { Vue, Component, PropSync } from 'vue-property-decorator'
@Component
export default class MyComponent extends Vue {
@PropSync('propA', { type: String, default: 'abc' }) syncedPropA!: string
}
父组件
<Name :name.sync="name"></Name>
<!--严格要求书写格式-->
import { Vue, Component, Watch } from 'vue-property-decorator' @Component export
default class MyComponent extends Vue { name="s" @Watch('name') function
nameChange(n,o){ console.log('新的名字'+n) } }
更多 vue-property-decorator 文章可以点击这里Github,掘金
自定义指令 v-model
如果想要通过 v-model 指令实现双向数据绑定,我们可以像下面这样进行尝试
<!-- children.vue -->
<template>
<h1>{{ msg }}</h1>
</template>
<script>
export default{
model:{
prop:'msg',//这个字段,是指父组件设置 v-model 时,将变量值传给子组件的 msg
event:'parent-event'//这个字段,是指父组件监听 parent-event 事件,也可以是自己定义的名字
},
props:{
msg:String //此处必须定义和model的prop相同的props,因为v-model会传值给子组件
},
mounted(){
//这里模拟异步将msg传到父组件v-model,实现双向控制
setTimeout(**=>{
let some = '3秒后出现的某个值';//子组件自己的某个值
this.$emit('parent-event',some);// 触发很重要,否则没办法双向绑定,对应上面的event
//将这个值通过 emit 触发parent-event,将some传递给父组件的v-model绑定的变量
},3000);
}
}
</script>
<!-- parent.vue -->
<template>
<children v-model="parentMsg"></children>
</template>
<script>
import children from 'path/to/children.vue';
export default{
components:{
children
},
data(){
return{
parentMsg:'test'
}
},
watch:{
parentMsg(newV,oldV){
console.log(newV,oldV);
//三秒后控制台会输出
//'3秒后出现的某个值','test'
}
}
}
</script>
在使用vue-property-decorator 这个库的时候,用到了 model 这个语法糖,使用基本方法如下
@Model('parent-event', { type: String, default: '' }) value!: string
如果想要实现双向绑定的 v-model 还需要去触发更新需要的值
this.$emit('parent-event', this.syncedvalue)
如果没有主动触发更新,则只能实现使用 v-model 的 props(这句话需要实际体验一下),没有实现双向绑定,下面看一个官方的例子
import { Vue, Component, Model } from 'vue-property-decorator'
@Component
export default class YourComponent extends Vue {
@Model('change', { type: Boolean }) readonly checked!: boolean
}
它等同于
export default {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: {
type: Boolean
}
}
}
// 仅仅是props的传递
如果你对这种方式还有疑问,可以结合Vue 官方文档进行理解,然后在回过头来看上面的实现。如下
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change'
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
现在在这个组件上使用 v-model
的时候:
<base-checkbox v-model="lovingVue"></base-checkbox>
这里的 lovingVue
的值将会传入这个名为 checked
的 prop。同时当 <base-checkbox>
触发一个 change
事件并附带一个新的值的时候,这个 lovingVue
的属性将会被更新。
注意你仍然需要在组件的 props
选项里声明 checked
这个 prop。
← 前言