这里总结了十一种vue中组件传值的方法(主要适用于vue2)
- props 和 $emit('自定义事件名') 父向子传值 子向父传值
$refs获取组件实例- 组件中的v-model 与 .sync语法糖
- 插槽
- eventBus事件总线(类似于发布订阅模式)
- provide 和 inject
- vuex 全局状态公共管理工具
- vue-router 路由传参
- listener 组件上的方法
- parent 获取子组件或父组件实例
- mixins 混入
接下来详细介绍一下这几种方法:
1. props 和 $emit('自定义事件名')
这两种都是大家在工作中常用的方法:在父组件中定义的变量 在子组件标签上通过 : 绑定 ,即可将父组件变量传递到子组件上,不加冒号表示传递过去的是字符串
<!-- 子组件标签 --> <child :age="age" age="age" />
而在子组件中 就可以使用props来接受父组件传递过来的值 type表示接受该值的数据类型,如果传递的值与定义的类型不符。就会抛出错误 default 表示该props的默认值。当父组件未传递值,而在子组件中又必须使用到该变量,我们可以用默认值的方式,来保证页面正常渲染
子组件中接收 props:{ age:{ type:Number, default:0 }, name:{ type:String, default:'' } }
但是在vue中组件传值是单向的数据流,这是一种规范也是必要的,我们想要在子组件中修改props接收到的值 不可以直接修改,会报错。但是我们可以通过vue上的 $emit 来自定义事件来通知父组件,修改该值,也可将想要修改的值传递给父组件,而父组件需要在子组件的标签上定义对应的自定义事件
子组件中的触发修改方法 fn(val){ this.$emit('updateAge',val) }
` <!-- 子组件标签 -->
<child :age="age" age="age" @updateAge="updateFn" />
`
2.$refs 获取组件实例
我们也可以通过给组件绑定上ref属性值,利用vue原型上的 $refs 方法来获取组件实例
( 给DOM元素绑定ref获取到的是dom节点)
我们知道vue的一大特点就是虚拟Dom,而在vue中每一个页面都是一个vue实例对象,我们定义的方法变量,都是挂载在vue实例上的, 在父组件中获取到子组件实例,我们就可以获得子组件上的方法以及属性,例如element-ui中的el-form组件,我们再进行手动校验表单元素的时候,调用的validate函数,就是利用这种方式
3. 组件中的v-model 与 .sync语法糖
v-model 大多用在input输入框上来进行数据双向绑定,在组件上同样适用该方法
`
<child v-model="age" />
这种方式在子组件中,也要用props来接收age,而在修改age的时候要调用$emit('input')` 并且不用在父组件中定义方法来修改,v-model本质上就是简化了第一种方法
注意: 一个组件上只能使用一次 v-model
而.sync语法糖完善了v-model的缺点,可以在组件上多次使用,它与v-model类似也可以当作是第一种方法的简化版 子组件中要修改数据,只需要在子组件中调用$emit('update:属性名',内容) 内容可以是例如: this.age+1
<!-- 子组件 --> <child :age1.sync="age1" :age2.sync="age2" />
虽然.sync在vue3中被废弃掉了,但在vue2中使用它也是非常nice的
4.插槽
首先插槽分为默认插槽,具名插槽,作用域插槽。 插槽的作用一般是用在我们抽离相同组件时,封装了相同的布局样式,而在相同地方显示不同元素,就可以借助插槽来完成,而我们也可以借助作用域插槽,完成数据从父 ==》子组件 通过插槽再流回父组件来完成数据的传递.
父组件中 <child :msg="msg"> <template #default="scope"> {{ scope }} </template> </child>
<!-- 子组件中 --> <div> <span> <slot :msg="msg"> 这是一个插槽 </slot> </span> </div>
5. eventBus事件总线(类似于发布订阅模式)
eventBus就是新建一个.js文件,引入Vue并向外暴露出一个vue实例,在两个要传递数据的组件中分别引入该文件,
在组件一内通过$on来监听事件,在组件二中通过 $emit 来触发事件就可以简单的完成数据交换了
` import { EventBus } from './event-bus.js'
事件监听
EventBus.$oon('事件名', {})
触发事件
EventBus.$off('emit', {})
移除事件监听
EventBus.$off('事件名', {})
只触发一次事件
EventBus.$oonce('事件名', {})
`
6. provide 和 inject
在父组件中提供暴露数据 provide 可以是一个对象,也可以是一个函数
在需要的子组件中注入数据 provide
两个组件必须具有后代关系(嵌套关系) 后代组件可以通过暴露提供的方法来修改数据
`
- 父组件 provide: function() { return { msg: this.msg, changeMsg: this.changeMsg } }, `
// 注入具有父子关系的组件,暴露出来的数据 // inject: ['msg', 'changeMsg'], inject: { msg: { type: String, default: '' }, changeMsg: { type: Function, default: function() {} } },
7. vuex 全局状态公共管理工具
vuex是一个非常好用的vue工具,里面内置了四个模块
- state 存储数据
- mutations 修改state数据的唯一入口,要修改state存储的数据,必须调用
mutations中的方法 - actions 异步方法,多用来封装接口来从而获取数据,在调用
mutations中的方法来更新state中的数据 - getters 类似于计算属性,可以提供暴露vuex各个模块中的数据方便获取
- modules 模块化,将vuex存储的数据细分,可以让每一个模块拥有自己的
state、mutation、action、getters,使得结构非常清晰,方便管理 为了防止modules中的数据混淆 vuex还提供了namespaced命名空间属性,当其未true时,我们通过获取state中的数据就必须加上模块名称,否则不需要
8. vue-router 路由传参
路由传参有两种方式:
- 路径参数
query通过调用$router.push({ path:'路径名/:参数名', query:{ 参数键值对} })在跳转后的页面中通过$route.query获取参数对象
2.params参数通过调用$router.push({ name:'对应模块的路由的name', params:{ 参数键值对} })在跳转后的页面中通过$route.params获取参数对象
注意:path不可以和params连用 name则无要求 。 路径参数刷新不丢失
9.$artts 和$listener
$attrs 父组件传递给子组件的数据,如果没有被子组件中的props接收,就会出现在 $attrs里
$listener 可以获取父组件上传递给子组件的自定义方法
10.$children 和 $parent 获取子组件或父组件实例
$children 获取所有子组件实例,类似于$refs 获取到对应子组件上的所有属性和方法
$parent 获取子组件的所有父组件实例
11.mixins 混入
可以提取所有类似的方法,直接混入到引入mixins的组建的对应属性中 (逻辑复用)
例如在一个项目中,一个页面有很多的dialog弹层组件,而弹层组建的显示,关闭,切换大多都是相同的,又或是vuex中的某些共享数据在多个页面使用,我们就可以将其定义到mixins中进行混入
mixins: ['逻辑对象名称']
`mixins 数据
export const xxxx = {
methods: {
showDialog() {
this.iShow = true
}
},
computed: {
...mapGetters(['xxx', 'xxx'])
},
created() {
console.log('每个页面都打印一个1')
}
}`