封装vant-popup组件遇到的数据双向绑定问题。v-model和sync两种解决⽅法需求:
需要在⽂章 、视频列表、帖⼦、直播、专题等评论区发布 评论。
评论发布框为⼀个弹出层。
使⽤vant实现。
我感觉多处⽤到了这个弹出层,准备封装成⼀个⼦组件以便调⽤。
哪有学做早餐的上图
这⾥遇到了个问题,就是不知道如何为⼦组件内部的孙组件的v-model传值。
这⾥数据我⼀直想不通的地⽅在于双向绑定需要事件,我想不到van-popup的事件是什么,后来才知道原来vue官⽅就说明了默认的v-model事件是input,默认绑定的值是value
查阅了好多地⽅,找到了两种解决⽅法,最终是在vant官⽅微信2群解决的,在此感谢 @A Lemon 提供的第⼀种⽅法和 @陪我笑闹⼈间提供的第⼆种⽅法
⾸先是使⽤第⼀种⽅法实现思路
1. ⽗组件内调⽤⼦组件使⽤v-model
2. ⼦组件内的孙组件(van-popup)的v-model拆分成:value和@input
3. 然后通过$emit完成数据同步
细节:
van-popup绑定的value对应从⽗组件内传来的props内的value
van-popup的input事件⽣成的新值弹射到⽗组件v-model对应的默认input事件参数
具体实现代码
先贴简单的⽗组件内调⽤⼦组件的代码
<comment-popup v-model="showPostDialog"/>
然后是⼦组件的代码
<template>
<van-popup
class="comment-popup"
position="bottom"
overlay-class="opacity"
:value="value"
@input="val => this.$emit('input', val)"
>
<!--内部构造多余,请忽略,弹出层内部slot⾃⼰随便写--> <div class="publish-comment van-hairline--top">
<van-uploader
ref="up"
v-show="upimage"
v-model="fileList"
:max-count="1"
:after-read="afterRead"
@delete="delImage"
/>
<div class="field">
<van-field
v-model="comment_content"
rows="3"
autosize
type="textarea"
maxlength="50"
placeholder="优质评论会被优先展⽰"
:
border="fal"
/>
拉伸运动<van-button
:disabled="disablePublish"秦昭王
@click="comment"
color="hotpink"
size="small"
>发布</van-button
>
</div>
<div class="fnbar">
<i class="icon image" @click="upImage"></i>
</div>
</div>
</van-popup>
</template>
<script>
import{ Button, Uploader, Popup, Field }from"vant"; Vue.u(Field)
.u(Uploader)
.u(Uploader)
地球的运动.u(Popup)
.u(Button);
export default{
name:"comment-popup",
// props: ["value" ],
阿根廷球星
props:{泰宁古城
value:{
type: Boolean,
default:fal
},
},
data:function(){
return{
牛肉丸怎么煮好吃
};
}
}
//多余的⽆⽤代码就不贴了(虽然也贴了⼀些了)
//......
</script>
第⼆种⽅法使⽤sync语法(vue2.3+)⽤到了computed的getter和tter
先贴官⽅⽂档,贴了看不懂,最后还是要看实现代码⽐较清楚。
具体实现代码
先贴⽗组件内调⽤⼦组件的代码
<comment-popup :popup.sync="showPostDialog"/>
然后是⼦组件的代码
<template>
<van-popup
class="comment-popup"
position="bottom"
overlay-class="opacity"
v-model="vanpopup"
>
</van-popup>
</template>
<script>
import{ Popup }from"vant";
Vue.u(Popup);
export default{
name:"comment-popup",
props:{
popup:{
type: Boolean,
default:fal
}
},
computed:{
vanpopup:{
get(){
return this.popup;
},
t(value){
this.$emit("update:popup", value);
}
}
}
};
</script>
看懂的⼈⾃然就懂,不然我这解释其实也很⽆⼒。
⾸先是⽗组件通过sync关键字设置了语法糖。
然后是把⼦组件内的孙组件van-popup的v-model双向绑定通过computed给他拆分成get和t。然后在t内调⽤$emit发射数据。
我⼀直两种⽅法都⽆法成功的原因是
1. 找不到popup的事件名。
2. 不清楚时间绑定的单向是否⽤到了vue的 $data 。
天秤座日期这⾥的两种⽅法都是直接把属性绑定到props上,不过更新数据都还是通过$emit发射的。关键点不在操作,⽽是认知,认知如何绑定到正确的属性,如何正确的发射事件,如何拆分。