为什么子组件不可以修改父组件的数据?
- vue 单向数据流指的父组件传值给子组件
- 这个影响是单向的,只能从父组件流向子组件,不能反向
实现组件之间信息通信
- props
* 父组件传值子组件
-
emit
* 子组件通过事件传值给父组件
- bus 兄弟间传值
// main.js
Vue.prototype.bus = new Vue();
// 传值组件
this.bus.$emit('sharetext', value)
// 接受的组件
this.bus.$on("sharetext", value => { //通过$on监听事件sharetext
this.value = value;
});
-
children | $refs )
- provide / inject
*隔代处理 一般不建议,因为数据多了,会污染
- $listeners
* 获取的是父组件传递进来的事件信息
* 当数据发生变化时,组件不会重新渲染, 此时用v-if来控制,让组件渲染
* 基于 @xxx=‘xxx’
- vuex
* 公共状态管理的插件
- $attrs
* 获取父组件传过来的属性信息(排除掉在props中注册过的)
* 都是基于v-bind绑定或者直接静态属性
一,要实现的功能
1.1,新建三个文件夹
src
component // 组件
propsFather.vue
propsChild.vue
view
props.vue
2.2,从 props 传值到 propsChild 中
image.png
二,解决方法
方法一
1.1,provide
provide
选项允许我们指定我们想要提供给后代组件的数据/方法。
1.2,props 页面中
这里页面样式就不展示了
<template>
<div class="hello">
<div class="mg-b20">我是 props 页面</div>
<input type="text" v-model="value" />
{{value}}---最外面组件
<propsFather :value="value"></propsFather>
</div>
</template>
<script>
import propsFather from "@/component/propsFather.vue";
export default {
name: "props",
components: { propsFather },
provide() { // 这里的 provide 传值
//这里传 this,父组件获取的就是this,但是显示的值是this.value,子组件获取的值,就是this.value,展示的值,也是this.value
//如果这里传的值是this.value,那么父组件获取的值就是this.value,但是子组件就接收不到值了
return { 'parent': this }
},
data() {
return { value:'' };
}
};
</script>
1.3,propsFather 页面中
<template>
<div class="childContent">
<div>我是 中间 组件</div>
<propsChild></propsChild>
</div>
</template>
<script>
import propsChild from "@/component/propsChild.vue";
export default {
name: "father",
components: { propsChild },
data() {
return { };
},
};
</script>
1.4,propsChild 页面中
<template>
<div class="childContent">
<div>我是 最里面 组件</div>
<div>value值:{{getVal}}</div>
</div>
</template>
<script>
export default {
name: "child",
inject: ["parent"],
data() {
return { };
},
computed: {
getVal() { return this.parent.value }
}
};
</script>
git.gif
方法二:attrs
2.1,props 页面中
<template>
<div class="hello">
<div class="mg-b20">我是 props 页面</div>
<input type="text" v-model="value" /> {{value}}---最外面组件
<propsFather :value="value" v-bind="$attrs"></propsFather>
</div>
</template>
<script>
import propsFather from "@/component/propsFather.vue";
export default {
name: "props",
components: { propsFather },
data() {
return { value:'' };
}
};
</script>
2.2,propsFather 页面中
<template>
<div class="childContent">
<div>我是 中间 组件</div>
value值:{{$attrs.value}}
<propsChild :value="$attrs.value"></propsChild>
</div>
</template>
<script>
import propsChild from "@/component/propsChild.vue";
export default {
name: "child",
components: { propsChild },
data() {
return { };
}
};
</script>
2.3,propsChild 页面中
<template>
<div class="childContent">
<div>我是 最里面 组件</div>
<div style="margin-top:10px;">value值:{{value}}</div>
</div>
</template>
<script>
export default {
name: "child",
data() {
return { };
},
props: {
value: { type: String }
},
};
</script>
第二种方法.gif
方法三:props 传值
2.1,props 页面中
<template>
<div class="hello">
<div class="mg-b20">我是 props 页面</div>
<input type="text" v-model="value" />
{{value}}---最外面组件
<propsFather :value="value"></propsFather>
</div>
</template>
<script>
import propsFather from "@/component/propsFather.vue";
export default {
name: "props",
components: { propsFather },
data() {
return { value:'' };
}
};
2.2,propsFather 页面中
<template>
<div class="childContent">
<div>我是 中间 组件</div>
value值:{{value}}
<propsChild :value="value"></propsChild>
</div>
</template>
<script>
import propsChild from "@/component/propsChild.vue";
export default {
name: "child",
props: {
value: { type: String }
},
components: { propsChild },
data() {
return {}
}
};
</script>
2.3,propsChild 页面中
<template>
<div class="childContent">
<div>我是 最里面 组件</div>
<div style="margin-top:10px;">value值:{{value}}</div>
</div>
</template>
<script>
export default {
name: "child",
props: {
value: { type: String }
}
data() {
return { };
},
};
</script>
git.gif
注:父子组件渲染的一个过程是: 父create => 子created => 子mouted => 父mouted
这里我写了一个 dome,链接:https://github.com/zhongmin2011/vue-dome