vue组件通信---父传子props、父传孙
一、概括组件间通信基本原则:1) 不要在子组件中直接修改父组件的状态数据2) 数据在哪, 更新数据的行为(函数)就应该定义在哪在通信中,无论是子组件向父组件传值还是父组件向子组件传值,他们都有一个共同点就是有中间介质,子向父的介质是自定义事件,父向子的介质是props中的属性。抓准这两点对于父子通信就好理解了。所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:...
props
一、概括
组件间通信基本原则:
1) 不要在子组件中直接修改父组件的状态数据
2) 数据在哪, 更新数据的行为(函数)就应该定义在哪
在通信中,无论是子组件向父组件传值还是父组件向子组件传值,他们都有一个共同点就是有中间介质,子向父的介质是自定义事件,父向子的介质是props中的属性。抓准这两点对于父子通信就好理解了。
所有的 prop 都使得其父子 prop 之间形成了一个单向下行绑定:父级 prop 的更新会向下流动到子组件中,但是反过来则不行。这样会防止从子组件意外改变父级组件的状态,从而导致你的应用的数据流向难以理解。
额外的,每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。这意味着你不应该在一个子组件内部改变 prop。如果你这样做了,Vue 会在浏览器的控制台中发出警告。
注意:
1) 此方式用于父组件向子组件传递数据
2) 所有标签属性都会成为组件对象的属性, 模板页面可以直接引用
二、案例
案例:
第一步:在父组件中引入子组件
第二步:在父组件中的子标签定义属性变量
第三步:在子组件中定义props属性接收传来的值
第四步:在子组件中直接使用传来的值
parent.vue
<template>
<div class="props-parent">
<h1>父亲</h1>
<input type="text" v-model.trim="msg" placeholder="请输入要传得值">
<!--第二步
定义传递的变量msgg -->
<child :msgg='msg'></child>
</div>
</template>
<script>
/**
* 第一步
*/
import child from './child';//引入子组件并在components注册
export default {
data() {
return {
msg:''
}
},
components:{
child
}
}
</script>
child.vue
<template>
<div class="props-child">
<h1>孩子</h1>
<!-- 第四步 -->
<p>父组件传来的值为:{{msgg}}</p>
</div>
</template>
<script>
export default {
data() {
return {
}
},
/**
* 第三步
* 定义props属性接收传来的值
*/
// props: ['msg'],//方式一
props:{//方式二,一旦这样定义必须传值过来
// msgg: String,//定义数据类型
// msgg: [String,Number],//多个可能的类型
msgg:{
type: String, //必填
required: true,//必填
default: 'muzidigbig' //默认值
}
}
}
</script>
方式二:this.$refs调用子组件的方法进行通讯
parent.vue
<template>
<div class="fatherToChild">
<h3>方式二:父组件调用子组件的方法进行传值</h3>
<!--用ref给子组件起个名字-->
<child ref="child"></child>
<button @click.stop="clickFather">点击父组件</button>
</div>
</template>
<script>
import child from "../../../components/child";
export default {
name: "fatherToChild",
components: {
child
},
data() {
return {
msg: { id: 1, name: "muzidigbig", age: 23, sex: "男" }
};
},
methods: {
clickFather() {
//调用子组件的方法,child是上边ref起的名字,emitEvent是子组件的方法。
this.$refs.child.emitEvent(this.msg);
}
}
};
</script>
child.vue
<template>
<div class="child">
<p v-if="msg1.id">{{msg1}}</p>
</div>
</template>
<script>
export default {
name: "child",
data() {
return {
msg1: {}
};
},
methods: {
emitEvent(msg1) {
this.msg1 = msg1;
console.log(msg1); //接收的数据--------->我是父组件中的数据
}
}
};
</script>
provide和inject
一、概括
通常,当我们需要将数据从父组件传递到子组件时,我们使用 props。想象一下这样的结构:你有一些深嵌套的组件,而你只需要来自深嵌套子组件中父组件的某些内容。在这种情况下,你仍然需要将 prop 传递到整个组件链中,这可能会很烦人。对于这种情况,我们可以使用 provide 和 inject 对。父组件可以作为其所有子组件的依赖项提供程序,而不管组件层次结构有多深。这个特性有两个部分:父组件有一个 provide 选项来提供数据,子组件有一个 inject 选项来开始使用这个数据。
上面这段话出自官方,内容也比较好理解,就是通常数据传递一层,我们使用prop就可以很好的解决,如果传递多层,再使用prop就不是很好的方案,这时需要provide和inject
二、案例
parent.vue
<template>
<div class="provide-inject">
<h3>provide-inject</h3>
<div>
<label for="name">姓名:</label>
<input type="text" name="" v-model="name" placeholder="请输入名字" />
<p>{{ name }}</p>
<!-- 父传子 -->
<inject :propName="name"></inject>
</div>
</div>
</template>
<script>
import Inject from "./components/inject.vue";
export default {
components: {
Inject,
},
data() {
return {
name: "木子",
};
},
// 父组件中返回要传给下级的数据
provide() {
return {
name: this.name,
};
},
};
</script>
<style scoped>
.provide-inject {
background: pink;
}
</style>
inject.vue 子
<template>
<div>
<p>props:--{{ propName }}</p>
<inject01></inject01>
</div>
</template>
<script>
import Inject01 from "./inject-01.vue";
export default {
name: "inject",
props: ["propName"],
components: {
Inject01,
},
data() {
return {};
},
};
</script>
inject.vue 孙
<template>
<div>
<p>inject-01:--{{ name }}</p>
</div>
</template>
<script>
export default {
name: "inject-01",
//引用vue name
inject: ["name"],
data() {
return {};
},
};
</script>
实际上,你可以把依赖注入看作一部分“大范围有效的 prop”,除了:
祖先组件不需要知道哪些后代组件使用它提供的属性
后代组件不需要知道被注入的属性来自哪里
提示:provide 和 inject 绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
总结:
官方其实不推荐在应用程序代码中直接使用,因为数据追踪比较困难,不知道那一层级声明了 provide 又或是哪些层级使用了 inject 。造成比较大的维护成本。因此,除组件库或高阶插件外,Vue建议用Vuex解决或其他办法处理。
更多推荐
所有评论(0)