前言
最近在刷面试题时,看见这个问题便做了个总结,欢迎各位补充!!!
1.props & $emit——适用于父子组件通信
父组件通过prop
向子组件传递数据,子组件通过$emit
触发事件给父组件传递数据。Vue基础,在此就不做过多的赘述。
这里提一下将一个对象的所有 property 都作为 prop 传入
// 父组件
post: {
id: 1,
title: 'My Journey with Vue'
}
<blog-post v-bind="post"></blog-post>
// 等价于
<blog-post
v-bind:id="post.id"
v-bind:title="post.title"
></blog-post>
2.ref——适用于父子组件通信
当ref作用在普通的 DOM 元素上使用,引用指向的就是 DOM 元素,如果用在组件上,引用就指向组件实例。进而我们能够获取到该组件的data
,能够调取该组件的方法
。
注意
当指定的元素出现在v-for
循环里时,此时返回的是一个数组,即使只循环一次,返回的也是一个数组。ref
指向普通元素时,也是如此
<div v-for="item in ids" :key="item">
<Child ref="child"></Child>
</div>
ids: [1, 2, 3]
this.$refs.child; // [VueComponent, VueComponent, VueComponent]
3.$children——适用于父子组件通信
返回当前实例的直接子组件数组,
1.
$children
只返回直接子组件 2.$children
并不保证顺序,也不是响应式的。
用法和ref相似
<Child>
<other></other>
</Child>
this.$children; // [VueComponent] 不包含other
4.$parent——适用于父子组件通信
返回当前实例的父实例,如果有的话
// 情形一
// 父组件
<Child></Child>
// 子组件
this.$parent; // 返回的是父组件的实例
// 情形二
// 父组件
<Other>
<Child></Child>
</Other>
// 子组件
this.$parent; // 此时返回的是Other组件的实例
5.$attrs——适用于隔代组件通信
包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 (class
和 style
除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class
和 style
除外),并且可以通过 v-bind="$attrs"
传入内部组件——在创建高级别的组件时非常有用。
// 父组件
<Child:abc="true" :flag="123"></Child>
// 子组件
props: ["flag"]
console.log(this.$attrs); // {abc: true}
// 传入内部组件
// 最外层组件
<Other :ids="ids"> </Other>
ids: [1, 2, 3]
// other组件
<Child v-bind="$attrs"></Child>
// 一旦在other组件的props中声明该属性,Child组件的$attrs将拿不到该ids属性
// props: ["ids"]
this.$attrs; // {ids: [1,2,3]}
// child组件
this.$attrs // {ids: [1,2,3]}
6.$root
访问当前组件树的根 Vue 实例。如果当前实例没有父实例,此实例将会是其自己。
// Vue 根实例
new Vue({
data: {
foo: 1
},
computed: {
bar: function () { /* ... */ }
},
methods: {
baz: function () { /* ... */ }
}
})
// 获取根组件的数据
this.$root.foo
// 写入根组件的数据
this.$root.foo = 2
// 访问根组件的计算属性
this.$root.bar
// 调用根组件的方法
this.$root.baz()
7.$listeners——适用于隔代组件通信
包含了父作用域中的 (不含 .native
修饰器的) v-on
事件监听器。它可以通过 v-on="$listeners"
传入内部组件——在创建更高层次的组件时非常有用。
// 传入内部组件
// 最外层组件
<Other @click="handleChlick"> </Other>
methods: {
handleChlick() {
console.log("handleChlick");
}
},
// other组件
<Child v-on="$listeners"></Child>
this.$listeners; // {click: ƒ}
this.$listeners.click() // handleChlick
// child组件
this.$listeners // {click: ƒ}
this.$listeners.click() // handleChlick
8.中央事件总线——适用于兄弟、父子、隔代组件
一个空的 Vue 实例作为中央事件总线(事件中心),然后通过bus.on监听触发的事件。从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
// bus.js
import Vue from "vue";
export default new Vue();
// 父组件
<Other></Other>
<Child></Child>
// other 组件
import bus from "./bus.js";
data() {
return {
age: 12
};
},
mounted() {
//绑定全局事件globalEvent
bus.$on("globalEvent", val => {
this.age = val;
console.log(this.age);
// 销毁全局事件
this.$once("hook:destroyed", () => {
bus.$off("globalEvent");
});
});
}
// child 组件
<el-button @click="handleChlick">click</el-button>
import bus from "./bus.js";
methods: {
handleChlick() {
bus.$emit("globalEvent", 24);// 点击事件触发之后,other的age值被改变,打印24
}
},
9.provide & inject——适用于隔代组件通信
provide
和inject
主要在开发高阶插件/组件库时使用。并不推荐用于普通应用程序代码中。
- 这对选项需要一起使用,以允许一个祖先组件向其所有子孙后代注入一个依赖,不论组件层次有多深,并在其上下游关系成立的时间里始终生效。如果你熟悉 React,这与 React 的上下文特性很相似。
provide
选项应该是一个对象或返回一个对象的函数。该对象包含可注入其子孙的 property。在该对象中你可以使用 ES2015 Symbols 作为 key,但是只在原生支持Symbol
和Reflect.ownKeys
的环境下可工作。inject
选项应该是:- 一个字符串数组,或
- 一个对象,对象的 key 是本地的绑定名,value 是:
- 在可用的注入内容中搜索用的 key (字符串或 Symbol),或
- 一个对象,该对象的:
from
property 是在可用的注入内容中搜索用的 key (字符串或 Symbol)default
property 是降级情况下使用的 value
提示:
provide
和inject
绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的 property 还是可响应的。
// 父组件
<Child></Child>
provide: {
foo: "test"
}
// child组件
<Other></Other>
inject: ["foo"],
mounted() {
console.log(this.foo); // test
}
// other组件
inject: ["foo"],
mounted() {
console.log(this.foo); // test
}
10.sync修饰符——适用于父子组件通信
Vue提供的一种缩写
// 父组件
<div class="wrapper">
{{ isVisible }}
<Child :isVisible.sync="isVisible"></Child>
<el-button @click="isVisible = true">parentClick</el-button>
</div>
data() {
return {
isVisible: true
};
},
// 子组件 此处不必通过props声明,如果有其他方式要使用该属性时再声明
<el-button @click="$emit('update:isVisible', false)">childClick</el-button>
11. native修饰符——适用于父子组件
在一个组件的根元素上直接监听一个原生事件
// 父组件
<Child @click.native="handleClick"></Child>
methods: {
handleClick() {
console.log("native!!");
}
},
// 子组件 点击根元素div所在的区域就会触发该事件
<div>
????
<el-button>childClick</el-button>
</div>
12.slot
通过插槽内容访问子组件中才的内部数据
// 父组件
<Child>
<template v-slot:default="{ user }">
{{ user.firstName }}
</template>
</Child>
// 子组件
<slot :user="user">
{{ user.lastName }}
</slot>
user: {
firstName: "胡",
lastName: "歌"
}
注意 v-slot 只能添加在 template 上 (只有当被提供的内容只有默认插槽时,组件的标签才可以被当作插槽的模板来使用。),这一点和已经废弃的 slot attribute 不同。
13.observable——适用于兄弟、父子、隔代组件
在小型项目中用来代替Vuex
// store.js
import Vue from 'vue'
// 通过Vue.observable创建一个可响应的对象
export const store = Vue.observable({
userInfo: {},
roleIds: []
})
// 定义 mutations, 修改属性
export const mutations = {
setUserInfo(userInfo) {
store.userInfo = userInfo
},
setRoleIds(roleIds) {
store.roleIds = roleIds
}
}
<template>
<div>
{{ userInfo.name }}
</div>
</template>
<script>
import { store, mutations } from '../store'
export default {
computed: {
userInfo() {
return store.userInfo
}
},
created() {
mutations.setUserInfo({
name: '子君'
})
}
}
</script>