Vue自定义组件数据的双向绑定方法

11 篇文章 0 订阅

Vue自定义组件数据的双向绑定方法

最近在学习饿了么的Vue项目制作的课件,课件内容给了我很大的启发。在开发过程中,数据的单一性可以让功能更加的安全。之前对Vue的学习,更多的停留在父子单向数据绑定,当子组件数据变化时,无法直接影响到父组件。经过这段时间的学习,慢慢找到了一些数据双向绑定的方法,稍微做了一下总结。

v-model

v-model本质上就是语法糖,具体使用方法如下:

父组件:

<!-- 父组件调用子组件 -->
<q-code v-model="isShowCode" :code-img="codeImg"></q-code>
export default {
    name: 'father',
    components: {
        QCode
    },
    data () {
        return {
            isShowCode: false
        };
    }
};

子组件:

<!-- 子组件 -->
<template>
    <div class="qCode-container" v-show="show">
        <h1 class="popup-header" @click="closePopup">微信咨询</h1>
    </div>
</template>

自定义model名的写法

export default {
    name:'qCode',
    model: {
        prop: 'isShow', // props对应的名字
        event: 'toggle' // 触发改变的事件名称
    },
    props: ['isShow'],
    data () {
        return {
            show: false // 用data来控制传递过来的数据,可以防止数据改变时第一次响应失效
        };
    },
    watch: {
    	isShow: function(newVal, oldVal) {
    		if (newVal !== oldVal) {
    			this.show = newVal
    		}
    	}
    },
    methods: {
        closePopup () {
            this.show = false;
            this.$emit('toggle', false); // 触发父组件数据的改变
        }
    }
};

使用默认的value的写法

export default {
    name:'qCode',
    props: {
    	value: {
    		type: Boolean,
    		default: false
    	}
    },
    data () {
        return {
            show: this.value // 用data来控制传递过来的数据,可以防止数据改变时第一次响应失效
        };
    },
    watch: {
    	isShow: function(newVal, oldVal) {
    		if (newVal !== oldVal) {
    			this.show = newVal
    		}
    	}
    },
    methods: {
        closePopup () {
            this.show = false;
            this.$emit('input', false); // 触发父组件数据的改变
        }
    }
};

.sync

.sync的官方文档:sync-修饰符

父组件:

<!-- 父组件调用子组件 -->
<rating-select :select-type.sync="selectType" :only-content.sync="onlyContent"></rating-select>
export default {
    name: 'father',
    components: {RatingSelect},
    data () {
        return {
            selectType: this.$store.state.RATING_CODE.ALL,
            onlyContent: true
        };
    },
    watch: {
        selectType (value) {
            console.log(value);
        },
        onlyContent (value) {
            console.log(value);
        }
    }
};

子组件:

<!-- 子组件 -->
<template>
    <div class="rating-select">
        <div class="rating-type border-1px">
            <span class="block positive" :class="{'active': intSelectType === $store.state.RATING_CODE.ALL}" @click="select($store.state.RATING_CODE.ALL)">{{desc.all}}<span class="count">{{ratings.length}}</span></span>
            <span class="block positive" :class="{'active': intSelectType === $store.state.RATING_CODE.POSITIVE}" @click="select($store.state.RATING_CODE.POSITIVE)">{{desc.positive}}<span class="count">{{positives.length}}</span></span>
            <span class="block negative" :class="{'active': intSelectType === $store.state.RATING_CODE.NEGATIVE}" @click="select($store.state.RATING_CODE.NEGATIVE)">{{desc.negative}}<span class="count">{{negatives.length}}</span></span>
        </div>
        <div class="switch border-1px">
            <i class="iconfont" :class="{'on': bOnlyContent}" @click="toggleContent">&#xe602;</i>
            <span class="text">只看有内容的评价</span>
        </div>
    </div>
</template>
export default {
    name: 'ratingSelect',
    props: {
        ratings: {
            type: Array,
            default () {
                return [];
            }
        },
        selectType: {
            type: Number,
            default () {
                return this.$store.state.RATING_CODE.ALL;
            }
        },
        onlyContent: {
            type: Boolean,
            default: false
        },
        desc: {
            type: Object,
            default () {
                return {
                    all: '全部',
                    positive: '满意',
                    negative: '不满意'
                };
            }
        }
    },
    data () {
        return {
        	// 用data来控制传递过来的数据,可以防止数据改变时第一次响应失效
            intSelectType: this.selectType,
            bOnlyContent: this.onlyContent
        };
    },
    watch: {
        selectType (value) {
            this.intSelectType = value;
        },
        onlyContent (value) {
            this.bOnlyContent = value;
        }
    },
    computed: {
        positives () {
            return this.ratings.filter((rating) => {
                return rating.rateType === this.$store.state.RATING_CODE.POSITIVE;
            });
        },
        negatives () {
            return this.ratings.filter((rating) => {
                return rating.rateType === this.$store.state.RATING_CODE.NEGATIVE;
            });
        }
    },
    methods: {
        select (type) {
            this.intSelectType = type;
            this.$emit('update:select-type', type);
        },
        toggleContent () {
            this.bOnlyContent = !this.onlyContent;
            this.$emit('update:only-content', this.bOnlyContent);
        }
    }
};

Object

当父组件传入的数据是个对象的时候,子组件对该对象的修改会直接影响到父组件。

父组件:

<!-- 父组件调用子组件 -->
<cart-control :food="food" @cart-add="drop"></cart-control>
export default {
    name: 'father',
    components: {CartControl},
    data () {
        return {
            food: {}
        };
    }
};

子组件:

<!-- 子组件 -->
<template>
    <div class="cart-control">
        <transition name="move">
            <div class="cart-decrease" v-show="food.count" @click.stop.prevent="minusCart"><i class="iconfont">&#xe608;</i></div>
        </transition>
        <div class="cart-count" v-show="food.count">{{food.count}}</div>
        <div class="cart-increase" @click.stop.prevent="addCart"><i class="iconfont">&#xe605;</i></div>
    </div>
</template>
export default {
    name:'cartControl',
    props: {
        food: {
            type: Object,
            default () {
                return {};
            }
        }
    },
    methods: {
        addCart (event) {
            if (!this.food.count) {
                Vue.set(this.food, 'count', 1);
            } else {
                this.food.count++;
            }
            this.$emit('cart-add', event.target);
        },
        minusCart () {
            this.food.count--;
        }
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值