说到vue组件传值,大概分为如下几种状况vue
父组件经过属性绑定将值传给子组件,子组件经过props进行接收vuex
父组件经过v-on监听方法,子组件经过$emit触发父组件的方法,将数据做为回调函数的参数传给父组件segmentfault
经过定义一个eventBus经过on和emit机制来实现事件的绑定和触发,实现数据的流动。如今常见的是用vuex来实现数据的共享和流动。api
除此外,今天遇到一个状况,组件A,B,C,D,四个组件之间的关系为嵌套关系,即组件A>组件B>组件C>组件D,可是组件D中想要触发组件A中的方法。
由于一开始的时候没有把设计到的数据放到vuex中且是作的公共组件的封装,放在vuex里面也不合适。在vue的官网上也看了,看到了inheritAttrs属性,第一开始没有看明白文档描述的意思,后来在segmentfault中看到一篇讲vue多层嵌套传值的文章。借助里面的demo和vue官网,终于好像有点明白多层嵌套传值的意思。函数
一开始也有考虑过子组件一层一层的往上emit,直到A组件监听到这个事件。可是考虑到B组件和C组件做为中间组件并无用到这个方法,只单纯定义个方法去吧数据emit到上一层组件中。每一层组件都须要去实现时间监听,按道理这个方法也能够实现,可是总以为方法有点笨,想着把这种方法做为planB,先尝试一下,若是找不到合适的解决方案的话,再采纳这个方案。
我想实现的方案简单来讲就是D能够触发A中的方法,可是中间组件不须要帮忙传递。学习
在解决问题以前,首先须要在vue官网上了解几个概念this
默认状况下父做用域的不被认做 props 的 attribute 绑定 (attribute bindings) 将会“回退”且做为普通的 HTML attribute 应用在子组件的根元素上。当撰写包裹一个目标元素或另外一个组件的组件时,这可能不会老是符合预期行为。经过设置 `inheritAttrs` 到 `false`,这些默认行为将会被去掉。而经过 (一样是 2.4 新增的) 实例 property `$attrs` 可让这些 attribute 生效,且能够经过 `v-bind` 显性的绑定到非根元素上。
在一开始的时候我读了两遍都没有读懂inheritAttrs的描述(理解能力真的稍微有点差)。我我的的理解是这样的。
假如A组件里面引用了B组件,A组件是父组件,B组件是子组件,A组件给B组件传值经过属性绑定,B组件经过prop接收,固然B组件确定只会接受本身须要的属性。假如B组件不须要name属性,可是A组件恰恰要传给B组件,可是B组件并无在props中接收,那么这个值确定是传过来了呀,可是那里去了呢,而后再来读这段话,“父做用域的不被认做 props 的 attribute 绑定 (attribute bindings) 将会“回退”且做为普通的 HTML attribute 应用在子组件的根元素上。”,意思就是name属性没有在props里接受,就会自动绑定到B组件的根组件上去。可是既然B组件既然不在props中接收他,确定是没有用,那确定不指望有这样的事情发生,“经过设置 inheritAttrs
到 false
,这些默认行为将会被去掉。”原来设置为false就能够阻止这样的行为。
回到咱们的需求,组件B和组件C做为一个中间组件,并不须要接收,就能够设置inheritAttrs为false便可实现code
class
和 style
除外)。当一个组件没有声明任何 prop 时,这里会包含全部父做用域的绑定 (class
和 style
除外),而且能够经过 v-bind="$attrs"
传入内部组件——在建立高级别的组件时很是有用。v-bind="$attrs"
传入内部组件.native
修饰器的) v-on
事件监听器。它能够经过 v-on="$listeners"
传入内部组件——在建立更高层次的组件时很是有用。v-on="$listeners"
传入内部组件!!!1.假如在D中想触发A中的handlePreview方法,首先A组件对该方法进行监听
2.在B组件和C组件中设置inheritAttrs为false,不作接收,而后把数据和事件往内部组件接着传(我本次需求只有方法,没有属性,为了加深学习印象就把 v-bind="$alert"
一块儿传递了)
3.到了D组件中,经过$emit触发A组件中的方法,顺利完成个人需求。
如下内容为代码片断(vue语法),大概表述出大概意思。
参考文章连接:vue多级嵌套组件传参
A组件component
<template> <div> A组件 <BComponent @handlePreview="preview"</BComponent> </div> </template>
B组件
<template> <div> B组件 <CComponent v-bind="$alert" v-on="$listeners" ></CComponent> </div> </template> <script> export default { name: 'b-component', inheritAttrs: false } </script>
C组件
<template> <div> C组件 <DComponent v-bind="$alert" v-on="$listeners" ></CComponent> </div> </template> <script> export default { name: 'c-component', inheritAttrs: false } </script>
D组件
<template> <div> D组件 <button @click="handleClick"></button> </div> </template> <script> export default { name: 'c-component', methods:{ handleClick(){ this.$emit('handlePreview') } } } </script>