props
能够是数组或对象,用于接收来自父组件的数据。javascript
// 父组件 List.vue
<template>
<div>
<List-item :str="str" :obj="obj" :arr="arr"></List-item>
</div>
</template>
<script>
import ListItem from "./ListItem";
export default {
data() {
return {
str: "给子组件传值",
obj: {msg: "给子组件传值"},
arr: [1, 2, 3]
}
},
components: {
ListItem
}
}
</script>
// 子组件 ListItem.vue
<template>
<div>
<div>{{msg}}</div>
<div>{{obj}}</div>
<div>{{arr}}</div>
</div>
</template>
<script>
export default {
props: {
msg: String, // props是字符串
obj: Object, // props是对象
arr: Array // props是数组
}
}
</script>
复制代码
.sync
修饰符 .sync 是 2.3.0+
新增,它对 props
起到了一种修饰的做用,使用 .sync
进行修饰的 props
意味子组件有修改它的意图,这种状况下它只起到一个标注性做用,有它没它都不会影响逻辑(后文会介绍使用 .sync 的其余做用)。html
使用 .sync
修改上边的代码:vue
// 父组件 List.vue
<template>
<!-- 这里不写 .sync 也不会影响结果 --> <List-item :title.sync="title" @update:title="updataTitle"></List-item> </template> <script> import ListItem from "./ListItem"; export default { data() { return { title: "我是title", } }, components: { ListItem }, methods: { updataTitle(res) { this.title = res; } } } </script> // 子组件 ListItem.vue <template> <div> <button @click="handleClick">Click me</button> <div>{{title}}</div> </div> </template> <script> export default { props: { title: String, }, methods: { handleClick() { // 子组件向父组件传值 this.$emit('update:title', '我要父组件更新 title'); } } } </script> 复制代码
使用.sync
向子组件传递 多个props:java
当咱们用一个对象同时设置多个 prop
的时候,也能够将这个 .sync
修饰符和 v-bind
配合使用:web
<text-document v-bind.sync="doc"></text-document> 复制代码
这样会把 doc
对象中的每个属性 (如 title) 都做为一个独立的 prop
传进去,而后各自添加用于更新的 `v-on 监听器。vuex
更多介绍,.sync 。api
这种方式,从严格意思上讲不是值的传递,而是一种"取"(不推荐直接经过实例进行值的获取)。数组
能够经过 Vue 的实例属性 $parent
得到父组件的实例,借助实例能够调用父实例中的方法,或者获取父实例上的属性,从而达到取值的目的。微信
// 父组件 List.vue
...
<script>
export default {
data() {
return {
message: "hello children",
msg: "hello"
}
},
methods: {
sendMessage() {
return this.message;
}
}
}
</script>
// 子组件 ListItem.vue
<template>
<div>
<div>{{data}}</div>
<div>{{msg}}</div>
</div>
</template>
<script>
export default {
data() {
return {
data: "",
msg: ""
}
},
mounted() {
this.data = this.$parent.sendMessage(); // 调用父实例中的方法
this.msg = this.$parent.msg; // 获取父实例中的属性
}
}
</script>
复制代码
拓展网络
子组件调用父组件中的方法:
经过 $parent
获取父实例 this.$parent.event
。
经过 props
传递方法。
经过 $emit
监听父组件中的方法 this.$emit("envnt")
。
$emit
发送一个自定义事件,事件名称是一个字符串。v-on
绑定子组件发送的自定义事件。// 父组件 List.vue
<template>
<div>
<!-- 监听自定义事件 -->
<List-item v-on:welcome="getWelcome"></List-item>
</div>
</template>
<script>
import ListItem from "./List-item";
export default {
components: {
ListItem
},
methods: {
getWelcome(data) {
alert(data)
}
}
}
</script>
// 子组件 ListItem.vue
<template>
<button @click="handleClick">Click me</button>
</template>
<script>
export default {
methods: {
handleClick() {
// 使用 $emit 发送自定义事件 welcome
this.$emit('welcome', 'hello');
}
}
}
</script>
复制代码
此方式同 $parent
,这里就不进行介绍了。
尽管存在 prop
和事件,有的时候你仍可能须要在 JavaScript 里直接访问一个子组件。为了达到这个目的,能够经过 ref
特性为这个子组件赋予一个 ID 引用。
<template>
<div>
<List-item ref="item" :title="title"></List-item>
<div>{{data}}</div>
</div>
</template>
<script>
import ListItem from "./List-item";
export default {
data() {
return {
title: "我是title",
data: ""
}
},
components: {
ListItem
},
mounted() {
this.data = this.$refs.item.message;
}
}
</script>
复制代码
非父子组件传值,能够使用一个空的 Vue 实例做为中央事件总线,结合实例方法 $on
和 $emit
完成传值操做。
Bus 的定义方式有如下三种:
Bus
抽离出来,组件有须要时进行引入。// Bus.js
import Vue from 'vue'
const Bus = new Vue()
export default Bus
复制代码
Bus
挂载到 Vue 根实例的原型上。import Vue from 'vue'
Vue.prototype.$bus = new Vue();
复制代码
Bus
注入到 Vue 根对象上。import Vue from 'vue'
const Bus = new Vue()
new Vue({
el:'#app',
data: {
Bus
}  
})
复制代码
下面案例中的 Bus
挂载在 Vue 原型上:
// 组件1 使用 $emit 向外部发布自定义事件
<template>
<button @click="handleClick"> Send Message</button>
</template>
<script>
export default {
data() {
return {
message: "给兄弟组件传值",
}
},
methods: {
handleClick() {
this.$Bus.$emit("sendMessage", this.message)
}
}
}
</script>
// 组件2 使用 $on 订阅外部发布的事件
<template>
<div>
{{data}}
</div>
</template>
<script>
export default {
data() {
return {
data: "",
}
},
mounted() {
this.$Bus.$on("sendMessage", data => {
this.data = data;
})
}
}
</script>
复制代码
注意:注册的 Bus
要在组件销毁时卸载,不然会屡次挂载,形成触发一次但多个响应的状况。
beforeDestroy () {
this.$Bus.$off('sendMessage', this.message);
}
复制代码
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的全部组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
图片引用自网络:
Vuex 的具体使用。
不是方法的方法:
子组件 A
经过事件 $emit
传值传给父组件。
父组件经过属性 props
传值给子组件 B
。
provide
选项容许咱们指定咱们想要提供给后代组件的数据/方法。
provide: function () {
return {
getMap: this.getMap
}
}
复制代码
而后在任何后代组件里,咱们均可以使用 inject
选项来接收指定的咱们想要添加在这个实例上的属性:
inject: ['getMap']
复制代码
provide
和 inject
主要为高阶插件/组件库提供用例。并不推荐直接用于应用程序代码中。
// 父级组件提供 'foo'
var Provider = {
provide: {
foo: 'bar'
},
// ...
}
// 子组件注入 'foo'
var Child = {
inject: ['foo'],
created () {
console.log(this.foo) // => "bar"
}
// ...
}
复制代码
然而,依赖注入仍是有负面影响的。它将你应用程序中的组件与它们当前的组织方式耦合起来,使重构变得更加困难。同时所提供的属性是非响应式的。这是出于设计的考虑,由于使用它们来建立一个中心化规模化的数据跟使用 $root 作这件事都是不够好的。若是你想要共享的这个属性是你的应用特有的,而不是通用化的,或者若是你想在祖先组件中更新所提供的数据,那么这意味着你可能须要换用一个像 Vuex 这样真正的状态管理方案了。
这个两个属性是 2.4
新增的特性。
$attrs:
官网介绍的很累赘,暂且理解为非 props
属性集合。更多介绍。
当一个组件中没有声明任何 prop 时,this.$attrs
能够获取到全部父做用域的属性绑定 (class 和 style 除外),而且能够经过 v-bind="$attrs"
传给其内部组件 —— 在建立高级别的组件时很是有用。
inheritAttrs:
控制元素属性是否显示在 dom 上,默认值为 true
。
默认状况下父做用域的不被认做 props 的特性绑定 (attribute bindings) 将会“回退”且做为普通的 HTML 特性应用在子组件的根元素上。当撰写包裹一个目标元素或另外一个组件的组件时,这可能不会老是符合预期行为。经过设置 inheritAttrs 到 false,这些默认行为将会被去掉。而经过 (一样是 2.4 新增的) 实例属性 $attrs 可让这些特性生效,且能够经过 v-bind 显性的绑定到非根元素上。
祖先组件:
<template>
<div>
<List-item :title="title" :message="message"></List-item>
</div>
</template>
<script> import ListItem from "./List-item"; export default { data() { return { title: "我是title", message: "传给后代" } }, components: { ListItem } } </script>
复制代码
父组件:
<template>
<div>
<h1>{{title}}</h1>
<h2>{{$attrs.message}}</h2>
<!-- 经过 v-bind="$attrs" 传入后代组件-->
<ListItem2 v-bind='$attrs'></ListItem2>
</div>
</template>
<script> import ListItem2 from './List-item2' export default { props: { title: String }, components: { ListItem2 }, // 默认为 true,若是传入的属性子组件没有 prop 接受,就会以字符串的形式做为标签的属性存在 <div message="传给后代"></div> // 设为 false,在 dom 中就看不到这些属性 <div>...</div> inheritAttrs: false } </script>
复制代码
后代组件:
<template>
<div>
{{$attrs.message}}
</div>
</template>
<script> export default { mounted() { console.log(this.$attrs) // {message: "传给后代"} } } </script>
复制代码
渲染出来的结果为:
在实际项目中确实有遇到插槽 后备内容
动态显示的状况,因此这里要补充一下插槽 后备内容
是如何与子组件进行通讯的。
插槽后备内容是指:写在父组件中,包含在子组件标签里的,与子组件中的 slot
对应。
<template>
<child-component>
我是插槽的后备内容
</child-component>
</template>
复制代码
好比这里有一个含有 slot
的 current-user
组件,它的模版结构是这样的:
<!-- 子组件 current-user.vue -->
<template>
<div>
<div>current-user组件</div>
<slot>插槽里默认显示:{{user.firstName}}</slot>
</div>
</template>
<script> export default { data() { return { user: { firstName: "zhao", lastName: "xinglei" } } } } </script>
复制代码
它的父组件是这样的:
<!-- 父组件 Users.vue -->
<template>
<div>
<div>我是Users组件</div>
<current-user>
我是插槽里的后备内容: {{user.lastName}}(我想显示为子组件中 user.lastName )
</current-user>
</div>
</template>
<script> import CurrentUser from './Current-User.vue' export default { components: { CurrentUser } } </script>
复制代码
咱们看到,在父组件 Users
中,为子组件 current-user
提供的后备内容中,想要显示子组件定义的 user.firstName
是不能作到的。
官网中提供一个指令 v-slot,它与 props
结合使用从而达到插槽后备内容与子组件通讯的目的。
咱们首先须要在子组件的 slot
中传递一个 props
(这个props
叫作插槽props),这里咱们起名叫 user
:
<!-- 子组件 current-user.vue -->
<template>
<div>
<div>current-user组件</div>
<slot :user="user">
插槽里默认显示:{{user.firstName}}
</slot>
</div>
</template>
复制代码
在父组件中,包含插槽后备内容的子组件标签上咱们绑定一个 v-slot
指令,像这样:
<template>
<div>
<div>我是Users组件</div>
<!-- slotProps里的内容就是子组件传递过来的 props -->
<!-- "user": { "firstName": "zhao", "lastName": "xinglei" } -->
<current-user v-slot="slotProps">
{{slotProps}}
</current-user>
</div>
</template>
复制代码
最后渲染出来的结果为:
官网给这种插槽起名叫作做用域插槽
,更多了解。
1. 组件之间传值无非就是经过属性、事件和操做 Vue 实例进行的。
2. 操做实例进行组件件通讯,实例属性 $root、$parent、$children 分别对应了根实例、父实例、子实例。
3 ref 子组件引用,在操做表单元素时会应用的到。
4. Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,简单的应用不要使用 Vuex。
5. Vue.observable() 让一个对象可响应,能够做为最小化的跨组件状态存储器(本文未提到)。
复制代码
我的博客同步更新:https: www.webinfoq.cn
微信公众号:webinfoq