目录
组件跨层级访问
访问外层组件
定向消息
ref(父组件访问子组件)
依赖注入
依赖注入,vue2.0实现源码
组件封装
组件二次封装
小结
组件跨层级访问
访问外层组件
// 获取 根组件 的数据
this.$root.pri;
// 写入 根组件 的数据
this.$root.pri = 2;
// 访问 根组件 的计算属性
this.$root.sm;
// 调用 根组件 的方法
this.$root.prism();
// 获取 父组件 的数据
this.$parent.pri;
// 写入 父组件 的数据
this.$parent.pri = 2;
// 访问 父组件 的计算属性
this.$parent.sm;
// 调用 父组件 的方法
this.$parent.prism();
定向消息
一级一级往上找直到找到name === componentName,把消息传过去
ref(父组件访问子组件)
<base-input ref="usernameInput" />
this.$refs.usernameInput.focus();
// $ref只能在mounted生命周期钩子函数被调用之后才能使用
// $parent和$root在各个生命周期钩子函数中都可以使用
this.$parent 和this.$root会造成强耦合,不易于复用,如上图,同一个组件在不同父组件中使用,报错了。
由此,为了解决这个问题引入了依赖注入
依赖注入
声明了当前组件依赖的父组件们(直系的祖宗)的外部prop有哪些。
// 根组件
export default {
name: "s-layout",
provide() {// 依赖注入
return {
fish: {
love: "tama"
}
}
}
}
// 直系子孙组件
export default {
name: "s-course-tab",
inject: ["fish"],// 接收注入的依赖
methods: {
say() {
alert(this.fish.love);
}
}
}
依赖注入,vue2.0实现源码
vue/inject.js at dev · vuejs/vue · GitHub
export function resolveInject(inject: any, vm: Component): ?Object {
if (inject) {
// inject is :any because flow is not smart enough to figure out cached
const result = Object.create(null);
const keys = hasSymbol ? Reflect.ownKeys(inject) : Object.keys(inject);
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
// #6574 in case the inject object is observed...
if (key === "__ob__") continue;
const provideKey = inject[key].from;
let source = vm;
// 开始查找注入--------------
while (source) {
if (source._provided && hasOwn(source._provided, provideKey)) {
result[key] = source._provided[provideKey];
// 找到里子组件最近的provide,结束查找注入的依赖
break;
}
source = source.$parent;
}
// 查找结束-------------------
if (!source) {
if ("default" in inject[key]) {
const provideDefault = inject[key].default;
result[key] =
typeof provideDefault === "function"
? provideDefault.call(vm)
: provideDefault;
} else if (process.env.NODE_ENV !== "production") {
warn(`Injection "${key}" not found`, vm);
}
}
}
return result;
}
}
依赖注入的优点:
- 祖先组件不需要知道哪些后代组件使用它提供的属性
- 后代组件不需要知道被注入的属性来自哪里
缺点:
- 组件间的耦合较为紧密,不易重构
- 提供的属性是非响应式(框架设计考虑)
组件封装
Element-UI二次封装
// v-bind="$attrs" v-on="$listeners" 透传,事件
<template>
<el-input v-bind="$attrs" v-on="$listeners"></el-input>
</template>
<style scoped>
.el-input >>> .el-input__inner {
border-top: none;
border-left: none;
border-right: none;
}
</style>
组件二次封装
- 通过v-bind=“$attr”来传递父组件上的prop class和 style
- 通过v-on="$listensers"来传递父组件上的事件监听器和事件修饰符
小结
- 组件跨层级访问
- 组件二次封装