一、组件通信(props)
1、说明
通过上一小节的学习我们已经知道了在Vue中怎么创建组件和使用组件,而组件与组件之间的相互使用避免不了数据之间的传递, 每一个组件实例的作用域是孤立的。这里的孤立并不是独立而且是指上下层之间的数据隔离,即不能在子组件的模板内直接引用父组件的数据。
组件通信的方式:
- 父组件跟子组件通信
- 子组件跟父组件通信
- 兄弟组件之间的通信
2、组件的分类
- 抽象通用组件
- 基本数据和默认值都是通过prop传入,没有在组件内依赖
ajax
异步数据 -
保证不修改prop,交互结果通过
v-on
等通知方式返回
- 基本数据和默认值都是通过prop传入,没有在组件内依赖
- 业务通用组件
- 在组件内依赖业务
ajax
异步数据 - 在需要进行
增删改查
操作的表格中,很难做到完全不修改prop,CURD
操作往往依赖于业务逻辑。如果不直接修改,则需要添加N多的v-on
事件
- 在组件内依赖业务
二、父组件给子组件传值
说明
vue 遵循了典型的单向数据流的原则,即数据总是由父组件传递到子组件,子组件在其内部可以有自己维护的数据,但它无权修改父组件传递给它的数据,当开发者尝试这样做的时候,vue 将会报错。这样做的好处是,防止多个子组件都尝试修改父组件状态时,让这一行为变得难以追溯。父组件通过绑定 props 的方式,将数据传递给子组件,但是子组件自己并没有权利修改这些数据,尽量不修改props值,如果要修改,只能把修改这一个行为通过 event 的方式报告给父组件,由父组件本身决定该如何处理数据
分类
- 静态传值
- 动态传值
使用步骤
- 在父组件实例中声明数据
- 在引入组件的自定义标签中使用
key='数据'
- 在子组件的实例中使用props['key'],与上面一步中的可以要一样
- 在子组件中使用数据
栗子
<div id="app">
<!--2.使用属性 :users='传递的数据'-->
<app-container :users="users" :title="title"></app-container>
</div>
<template id="appContainer">
<div>
<!--4. 在子组件中使用数据-->
<h3 v-text="title"></h3>
<table>
<tr v-for="(user, index) in users" :key="index">
<td v-text="user.id"></td>
<td v-text="user.name"></td>
<td v-text="user.age"></td>
</tr>
</table>
</div>
</template>
<script>
new Vue({
el: '#app',
// 1. 在data中声明数据 users 数组
data: {
title: '用户列表',
users: [
{'id': 1, name: '1号技师', 'age': 18},
{'id': 2, name: '2号技师', 'age': 19},
{'id': 3, name: '3号技师', 'age': 20},
{'id': 4, name: '4号技师', 'age': 21},
{'id': 5, name: '5号技师', 'age': 22},
{'id': 6, name: '6号技师', 'age': 23},
],
},
components: {
'app-container': {
// props: ['users'],
/* 3. 在组件的实例化的对象中使用 props属性来获取数据 */
props: {
'title': {
type: String,
},
'users': {
/*声明传递过来数据的类型 类型可以是任意对象*/
type: Array,
/*是否是必要数据,默认为false*/
required: true,
}
},
template: '#appContainer',
}
}
});
</script>
总结
父组件通过 props 向下传递数据给子组件组件中的数据共有三种形式:data、props、computed
Prop 大小写
- 说明
- 由于HTML特性不区分大小写,在子组件定义prop时,使用了驼峰式大小写(camelCase)命名法。
- 驼峰式大小写的prop用于特性时,需要转为短横线隔开(kebab-case)。例如,在prop中定义的myName,在用作特性时需要转换为my-name。
- 示例代码
<template> <div class="home"> <index :names="names" :came-case="camelCase"></index> </div> </template> <script> import Index from "../components/Index"; export default { name: "home", components: { Index, }, data() { return { camelCase: "传递数据", names: ["1号技师", "2号技师", "3号技师"] } } }; </script>
三、子组件给父组件传值
说明
子组件使用$emit来触发一个自定义事件,并传递一个参数 父组件中的子标签中监听该自定义事件并添加一个响应该事件的处理方法
步骤
- 在子组件传值的标签上绑定一个点击事件
- 在击事件的函数中使用$emit来触发一个事件,并传递数据
- 在父组件中的子标签中监听该自定义事件并添加一个响应该事件的处理方法
栗子
子组件
<template>
<div id="#child">
<input type="text" v-model="msg">
<!-- 1. 定义事件 -->
<button @click="sendParentData">发送数据给父组件</button>
</div>
</template>
<script>
export default {
name: "Child",
data() {
return {
msg: "请输入要发送的数据",
}
},
methods: {
// 2. 发送数据
sendParentData() {
this.$emit("takeChildData", this.msg)
}
}
}
</script>
父组件
<template>
<div id="#parent">
<p v-text="msg"></p>
<!-- 4. 在子组件上注册-->
<child @takeChildData="takeChildData"></child>
</div>
</template>
<script>
import Child from "./Child";
export default {
name: "Parent",
data() {
return {
msg: "",
}
},
components: {Child},
// 3 父组件定义接受数据的自定义事件
methods: {
takeChildData(data) {
this.msg = data;
}
}
}
</script>
四、非父子组件传值
Vue 中没有直接子对子传参的方法
如果一定需要子对子传参,可以先从传到父组件,再传到子组件(相当于一个公共bus文件)
为了解决这种问题,Vue 封装了一个状态管理工具 Vuex,可以很方便实现组件之间的参数传递