封装vant-popup组件遇到的数据双向绑定问题。v-model和sync两种解决方法
需求:需要在文章 、视频列表、帖子、直播、专题等评论区发布 评论。评论发布框为一个弹出层。使用vant实现。我感觉多处用到了这个弹出层,准备封装成一个子组件以便调用。上图这里遇到了个问题,就是不知道如何为子组件内部的孙组件的v-model传值。这里数据我一直想不通的地方在于双向绑定需要事件,我想不到van-popup的事件是什么,后来才知道原来vue官方就说明了默认的v-...
·
需求:
- 需要在文章 、视频列表、帖子、直播、专题等评论区发布 评论。
- 评论发布框为一个弹出层。
- 使用vant实现。
我感觉多处用到了这个弹出层,准备封装成一个子组件以便调用。
上图
这里遇到了个问题,就是不知道如何为子组件内部的孙组件的v-model传值。
这里数据我一直想不通的地方在于双向绑定需要事件,我想不到van-popup的事件是什么,后来才知道原来vue官方就说明了默认的v-model事件是input,默认绑定的值是value
查阅了好多地方,找到了两种解决方法,最终是在vant官方微信2群解决的,在此感谢 @A Lemon 提供的第一种方法和 @陪我笑闹人间 提供的第二种方法
首先是使用第一种方法实现思路
- 父组件内调用子组件使用v-model
- 子组件内的孙组件(van-popup)的v-model拆分成:value和@input
- 然后通过$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="false"
/>
<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.use(Field)
.use(Uploader)
.use(Popup)
.use(Button);
export default {
name: "comment-popup",
// props: ["value" ],
props: {
value: {
type: Boolean,
default: false
},
},
data: function() {
return {
};
}
}
//多余的无用代码就不贴了(虽然也贴了一些了)
//......
</script>
第二种方法使用sync语法(vue2.3+)用到了computed的getter和setter
先贴官方文档,贴了看不懂,最后还是要看实现代码比较清楚。
具体实现代码
先贴父组件内调用子组件的代码
<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.use(Popup);
export default {
name: "comment-popup",
props: {
popup: {
type: Boolean,
default: false
}
},
computed: {
vanpopup: {
get() {
return this.popup;
},
set(value) {
this.$emit("update:popup", value);
}
}
}
};
</script>
看懂的人自然就懂,不然我这解释其实也很无力。
首先是父组件通过sync关键字设置了语法糖。
然后是把子组件内的孙组件van-popup的v-model双向绑定通过computed给他拆分成get和set。然后在set内调用$emit发射数据。
我一直两种方法都无法成功的原因是
- 找不到popup的事件名。
- 不清楚时间绑定的单向是否用到了vue的 $data 。
这里的两种方法都是直接把属性绑定到props上,不过更新数据都还是通过$emit发射的。关键点不在操作,而是认知,认知如何绑定到正确的属性,如何正确的发射事件,如何拆分。
更多推荐
已为社区贡献1条内容
所有评论(0)