父组件向子组件传值
1. 通过属性传值 props
props
可以是数组或对象,用于接收来自父组件的数据。
// 父组件 List.vue
// 子组件 ListItem.vue
{{msg}}
{{obj}}
{{arr}}
2. 使用修饰符 .sync
修饰符 .sync 是 2.3.0+
新增,它对 props
起到了一种修饰的作用,使用 .sync
进行修饰的 props
意味子组件有修改它的意图,这种情况下它只起到一个标注性作用,有它没它都不会影响逻辑(后文会介绍使用 .sync 的其他作用)。
使用 .sync
修改上边的代码:
// 父组件 List.vue
// 子组件 ListItem.vue
{{title}}
使用.sync
向子组件传递 多个props:
当我们用一个对象同时设置多个 prop
的时候,也可以将这个 .sync
修饰符和 v-bind
配合使用:
这样会把 doc
对象中的每一个属性 (如 title) 都作为一个独立的 prop
传进去,然后各自添加用于更新的 `v-on 监听器。
更多介绍,.sync 。
3. 通过 $parent 获取父组件实例的方法或者属性
这种方式,从严格意思上讲不是值的传递,而是一种"取"(不推荐直接通过实例进行值的获取)。
可以通过 Vue 的实例属性 $parent
获得父组件的实例,借助实例可以调用父实例中的方法,或者获取父实例上的属性,从而达到取值的目的。
// 父组件 List.vue
...
// 子组件 ListItem.vue
{{data}}
{{msg}}
拓展
子组件调用父组件中的方法:
- 通过
$parent
获取父实例this.$parent.event
。 - 通过
props
传递方法。 - 通过
$emit
监听父组件中的方法this.$emit("envnt")
。
子组件向父组件传值
1. 通过事件传值 $emit
- 子组件使用
$emit
发送一个自定义事件,事件名称是一个字符串。 - 父组件使用指令
v-on
绑定子组件发送的自定义事件。
// 父组件 List.vue
// 子组件 ListItem.vue
2. 通过 $children 获取子组件实例
此方式同 $parent
,这里就不进行介绍了。
3. 通过 ref 注册子组件引用
尽管存在 prop
和事件,有的时候你仍可能需要在 JavaScript 里直接访问一个子组件。为了达到这个目的,可以通过 ref
特性为这个子组件赋予一个 ID 引用。
{{data}}
更多 ref 用法。
兄弟组件传值
1. Bus 中央事件总线
非父子组件传值,可以使用一个空的 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 向外部发布自定义事件
// 组件2 使用 $on 订阅外部发布的事件
{{data}}
注意:注册的 Bus
要在组件销毁时卸载,否则会多次挂载,造成触发一次但多个响应的情况。
beforeDestroy () {
this.$Bus.$off('sendMessage', this.message);
}
2. Vuex 状态管理器
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
图片引用自网络:
Vuex 的具体使用。
3. 通过父组件进行过渡
不是方法的方法:
- 子组件
A
通过事件$emit
传值传给父组件。 - 父组件通过属性
props
传值给子组件B
。
深层次嵌套组件传值
1. 依赖注入 provide/inject
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. $attrs/inheritAttrs
这个两个属性是 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 显性的绑定到非根元素上。
祖先组件:
父组件:
{{title}}
{{$attrs.message}}
后代组件:
{{$attrs.message}}
渲染出来的结果为:
总结
1. 组件之间传值无非就是通过属性、事件和操作 Vue 实例进行的。
2. 操作实例进行组件件通信,实例属性 $root、$parent、$children 分别对应了根实例、父实例、子实例。
3 ref 子组件引用,在操作表单元素时会应用的到。
4. Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式,简单的应用不要使用 Vuex。
- 个人博客同步更新:https: www.webinfoq.cn
- 微信公众号:webinfoq