前言
在vue是实际工作中碰到一个问题,就是props传递的数据在组件内无法修改,好奇一下其中的问题
props描述
在Vue2中组件的props的数据流动改为了只能单向流动,即只能由组件外(调用组件方)通过组件的DOM属性attribute传递props给组件内,组件内只能被动接收组件外传递过来的数据,并且在组件内,不能修改由外层传来的props数据。
不能修改props是值不能直接修改props传递的对象。但有一种情况下是特例(实际不是很严谨的特例),修改props数据的对象。
props传递的数据类型为Object
export default {
name:'demo',
props:['pData']
}
如果pData是Number/String等类型的数据,直接修改Vue会报错,但是如果pData是Object类型的数据,虽然不能直接修改pData的指向,但是可以修改pData的属性,来间接达到数据绑定。
这样,子组件改变pData的属性,父组件也会同步。原理是,javascript中Object对象对应的是内存地址,当对象的属性改变时,对象的内存地址是不变的。
computed会对属性进行深度的计算,属性发生改变也会改变的。
但是还有一种情况要特殊看待,当父组件传递的props对象在子组件要操作一个不存在的属性时,这种情况父类和子类都不会发生变更触发。
原理:Vue会对内部数据对象进行getter/setter处理,方便自己监听变化,不存在的属性直接添加是不会转换成vue需要的对象。
解决:将不存在的数据通过Vue.set()或者this.$set()进行转化。
// 截取饿了吗cartcontrol组件代码
/*
传递过来的props中的food是某一商品的json数据
其中不存在用户选择的数量(count数据)
即:food.count 等于 undefined
*/
export default{
name:'cartcontrol',
props:{
food:{
type:Object
}
},
methods: {
add() {
// 增加一个数量
if(this.food.count){
this.food.count += 1
}else{
/*
因为本身不存在count数据,
如果直接修改如:this.food.count = 1会存在上述问题
(无法显示,无法computed,无法与父类双向绑定)
所以要先this.$set(this.food,'count',1),将属性转化getter/setter形式
转换之后对这个属性操作都可以进行直接修改
*/
this.$set(this.food,'count',1)
}
},
remove() {
// 减少一个数量
if(this.food.count || this.food.count>1){
this.food.count -= 1;
}else{
this.food.count = 0;
}
}
},
mounted:function () {
}
}
如何在Vue2中实现组件props双向绑定
使用data副本存储props
如何处理props数据双向绑定
v-model进行双向绑定
最近看了一些Vue2的双向绑定的方法,看到v-model来解决的方法。
方法实际同理上一条,v-model是vue封装的一个类似语法糖的东东。实际会被解析成为
<div v-model='something'></div>
//转换为
<div :val='something' @input='something= $event.target.value '></div>
<template>
<div class="modal" :value="value" v-show="visible">
<div class="close" @click="cancel">X</div>
</div>
</template>
<script>
export default {
props: {
value: {
type: Boolean,
default:false
}
},
data () {
return {
visible:false
}
},
watch:{
value(val) {
console.log(val);
this.visible = val;
},
visible(val) {
this.$emit('input', val);
}
},
methods:{
cancel(){
this.visible = false;
}
},
mounted() {
if (this.value) {
this.visible = true;
}
}
}
</script>
computed不会去计算没有被vue格式化处理的数据