vue组件之间的传值大致分为三种:父组件给子组件传值,子组件给父组件传值,兄弟组件之间传值
vue组件之间简单的数据传递,如果组件之间传递的数据比较复杂,建议使用vue的状态管理模式 vuex
父组件给子组件传值
1.父组件通过props给子组件传值
props 就是父组件给子组件标签上定义的属性,用来接收父组件传递的数据,props 的值可以是字符串数组,也可以是各自的名称和类型,用法和 data 中的数据用法一样,在子组件中只能使用该值,不能修改
2.父组件通过$ref给子组件传值
ref 用于给元素或子组件注册引用信息,引用信息将会注册在父组件的 refs 对象上,父组件通过refs对象上,父组件通过ref 获取到在子组件里定义的属性和方法,通过调用方法给子组件传递数据
3.父组件通过$children给子组件传值
children为当前组件的直接子组件,是一个无序的数组,父组件通过 children 访问子组件并传递数据,$ children 并不保证顺序,也不是响应式的,如果能清楚的知道子组件的顺序,可以使用下标来操作对应的子组件
4.父组件通过provide/inject给子孙组件传值
provide/inject 组合以允许一个祖先组件向其所有子孙后代组件注入一个依赖(属性和方法),不论组件层次有多深,并在其上下游关系成立的时间里始终生效,从而实现跨级父子组件通信,主要在开发高阶插件/组件库时使用
props和 r e f 和 ref和 ref和children和provide/inject的主要区别:
1.props 侧重于数据的传递,并不能获取子组件里的属性和方法,适用于自定义内容的使用场景
2.$ref 侧重于获取子组件里的属性和方法,并不是太适合传递数据,并且 ref 常用于获取dom元素,起到选择器的作用
3.$children 侧重于获取所有的直接子组件,得到的是一个无序的数组,并不太适合向多个子组件传递数据
4.provide/inject 侧重于在开发高阶插件/组件库时使用,并不推荐用于普通应用程序代码中
子组件给父组件传值
1.子组件通过触发$emit事件给父组件传值
$emit 的第一个参数为自定义的事件,第二个参数为要传递给父组件的值,父组件在子组件标签上绑定自定义事件来接收子组件传递的数据
2.子组件通过$parent给父组件传值
$parent 可以用来从一个子组件访问父组件并传递数据
兄弟组件之间传值
兄弟之间传值通过eventBus
eventBus 就是一个vue实例来作为全局的事件总线,兄弟组件之间通过 eventBus. on 和 eventBus.on和eventBus.emit 注册触发事件来传递数据
(1)props / $emit 适用 父子组件通信
(2)ref 与 $parent / $children 适用 父子组件通信
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
$parent / $children:访问父 / 子实例
(3)EventBus ($emit / $on) 适用于 父子、隔代、兄弟组件通信
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
(4)$
attrs/$
listeners 适用于 隔代组件通信
$attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。
当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),
并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
l i s t e n e r s : 包 含 了 父 作 用 域 中 的 ( 不 含 . n a t i v e 修 饰 器 的 ) v − o n 事 件 监 听 器 。 它 可 以 通 过 v − o n = " listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on=" listeners:包含了父作用域中的(不含.native修饰器的)v−on事件监听器。它可以通过v−on="listeners" 传入内部组件
(5)provide / inject 适用于 隔代组件通信
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
(6)Vuex 适用于 父子、隔代、兄弟组件通信
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样使得我们可以方便地跟踪每一个状态的变化。
props
和 $emit + v-on
通过 props
将数据在组件树中进行⾃上⽽下的传递;
通过 $emit
和 v-on
来作信息的向上传递。
EventBus
可通过 EventBus 进⾏信息的发布与订阅。
Vuex
全局状态管理库。可通过它来进行全局数据流的管理。
常规使用
{
state:{userInfo:""} // this.$store.state.userInfo
mutations:{
// this.$store.commit("setUserInfo",参数值)
setUserInfo(state,value){
state.userInfo=value
this.commit('setXxx',value值)
},
setXxx(state,value){
state.userInfo=value
}
},
actions:{
// 调用actions方法 this.$store.dispatch("refreshUserInfo",参数值)
refreshUserInfo(store,value){
setTimeout(()=>{
// 通过actions调用mutations
store.commit("setUserInfo",参数值)
},2000)
}
}
// 常规结合map使用
import {mapState,mapMutations} from 'vuex'
computed:{
...mapState(["userInfo"])
...mapState({
userInfoxxx:'userInfo'
})
},
methods:{
// actions与mutations一样的
...mapMutations(['setUserInfo]),
...mapState({
setUserInfoxxx:'setUserInfo'
})
}
}
// 模块化的使用
import login from 'login地址'
import my from 'my地址'
{
modules:{
login,
my
}
}
// login
export default {
namespaced:true, // 命名空间
// state加不加namespaced都一样
// state使用:this.$store.state.模块名(login).属性名(loginState)
state:{
loginState:false
},
// mutations如果不加namespaced和常规使用一样的 this.$store.commit('方法名',参数值)
// mutations加namespaced this.$store.commit('模块名/方法名',参数值)
mutations:{
setLoginState(state,value){
state.loginState=value
// mutations调用其它模块的mutations方法 this.commit("模块名(有命名空间就加)/方法名",参数,{root:true})
}
},
actions:{
// actions如果不加namespaced和常规使用一样的 this.$store.dispatch('方法名',参数值)
// actions加namespaced this.$store.dispatc('模块名/方法名',参数值)
refreshLoginState(store,value){
setTimeout(()=>{
// actions调用其它模块的actions方法 store.dispatch("模块名(有命名空间就加)/方法名",参数,{root:true})
// actions调用其它模块的mutations方法 store.commit("模块名(有命名空间就加)/方法名",参数,{root:true})
store.commit("setLoginState",true)
},2000)
}
}
}
// 模块化命名空间结合map使用
import {mapState,mapMutations,mapActions} from 'vuex'
computed:{
...mapState("有命名空间就加",["属性名"]), // 使用 this.属性名
},
methods:{
...mapMutations("有命名空间就加",['方法名']) // 使用 this.方法名(参数值)
...mapMutations(['有命名空间就加/方法名']) // 使用 this['有命名空间就加/方法名'](参数值)
...mapActions("有命名空间就加",['方法名']) // 使用 this.方法名(参数值)
...mapActions(['有命名空间就加/方法名']) // 使用 this['有命名空间就加/方法名'](参数值)
}
$attrs
和 $listeners
在 Vue 2.4 版本中加⼊的 $attrs
和 $listeners
可以用来作为跨级组件之间的通信机制。
provide
和 inject
传: provide(){
return {
abc:this[data属性与methods方法]
}
},
收:
inject:["abc(属性名)"],
inject:{
cde:{
from:"abc",
default默认值(和props定义默认值一样,区分原始值与引用值)
}
}
一般只用于高阶组件向低阶组件传值,provide它的属性值不能直接调用
由于 provide
和 inject
可以允许⼀个祖先组件向它的所有⼦孙组件注⼊⼀个依赖(不论组件层次有多深),并在其上下游关系成⽴的时间⾥始终⽣效,因此这种机制也就成为了一种跨组件通信的手段。
父子组件怎么传值
父组件向子组件传值
父组件在使用子组件的时候绑定一个自定义属性,属性值就是父组件的传递给子组件数据。子组件在通过props接收
子组件传给父组件
子组件通过this.$emit(“自定义事件名”,数据)给父组件传值,父组件通过这个自定义事件来接收参数
兄弟组件之间的传参 通过evenbus
父组件向子组件传值:
1)子组件在props中创建一个属性,用来接收父组件传过来的值;
2)在父组件中注册子组件;
3)在子组件标签中添加子组件props中创建的属性;
4)把需要传给子组件的值赋给该属性
子组件向父组件传值:
1)子组件中需要以某种方式(如点击事件)的方法来触发一个自定义
的事件;
2)将需要传的值作为$emit的第二个参数,该值将作为实参传给响应事
件的方法;
3)在父组件中注册子组件并在子组件标签上绑定自定义事件的监听。
VUE自定义组件的步骤
第一步:在components目录新建你的组件文件(indexPage.vue),script一定
要export default {}
第 二 步 : 在 需 要 用 的 页 面 ( 组 件 ) 中 导 入 : import indexPage from
‘@/components/indexPage.vue’
第三步:注入到vue的子组件的components属性上面,components:{indexPage}
第四步:在template视图view中使用
例如有indexPage命名,使用的时候则index-page
封装 vue 组件的过程
使用Vue.extend 方法创建一个组件,然后使用 Vue.component 方法注册组件。子组件需要数据,可
以在 props 中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit 方法、
VUE父子组件之间如何实现数据双向绑定
vm. e m i t 这 种 方 式 是 最 常 见 , 也 是 最 简 单 的 。 子 组 件 通 过 emit 这种方式是最常见,也是最简单的。子组件通过 emit这种方式是最常见,也是最简单的。子组件通过emit函数触发一个方法给父组件,附加上回传的值。父组件做该方法监听即可得到子组件回传的值。
$emit方法 优点:简单易懂
缺点:代码多,需要父组件做方法绑定并监听
v-model指令
优点:父组件只要绑定一个变量即可
缺点:需要理解v-model的原理
v-model
在vue中,v-model是用来进行数据双向绑定的一个语法糖,比如说用在input上,输入框数据变化,v-model绑定的对应的值也会跟着变化,无需单独获取。
其实v-model还可以在自定义组件中使用,可以被拆解为props:value和event:input,也就是说组件必须接收一个value值以及名为input的自定义事件,就可以在自定义组件上使用v-model了。