谈谈vue中组件传值的几个方法

113 阅读2分钟

这里总结了十一种vue中组件传值的方法(主要适用于vue2)

  1. props 和 $emit('自定义事件名') 父向子传值 子向父传值
  2. $refs 获取组件实例
  3. 组件中的v-model 与 .sync语法糖
  4. 插槽
  5. eventBus事件总线(类似于发布订阅模式)
  6. provide 和 inject
  7. vuex 全局状态公共管理工具
  8. vue-router 路由传参
  9. arttsartts 和 listener 组件上的方法
  10. childrenchildren 和 parent 获取子组件或父组件实例
  11. 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

两个组件必须具有后代关系(嵌套关系) 后代组件可以通过暴露提供的方法来修改数据

`

  1. 父组件 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存储的数据细分,可以让每一个模块拥有自己的statemutationactiongetters,使得结构非常清晰,方便管理 为了防止modules中的数据混淆 vuex还提供了 namespaced命名空间属性,当其未true时,我们通过获取state中的数据就必须加上模块名称,否则不需要

8. vue-router 路由传参

路由传参有两种方式:

  1. 路径参数 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')
  }
}`