首页 > 其他分享 >【Vue】组件传值的六种方法

【Vue】组件传值的六种方法

时间:2023-11-15 18:38:43浏览次数:36  
标签:Vue 六种 default vue export child 组件 import 传值

Vue 组件之间的通信大概归类为:

  • 父子组件通信: props;ref;$attrs / $listeners;$parent / $children
  • 兄弟组件通信: eventBus;vuex
  • 跨级通信: eventBus;Vuex;$attrs / $listeners

一、props/$emit
1.父组件向子组件传值
通过 props 传值。
父组件的代码:

<template>
  <div class="section">
    <child :list="list"></child>
  </div>
</template>
<script>
import child from './child.vue'
export default {
  components: { child },
  data() {
    return {
      list: ['a1', 'b2', 'c3']
    }
  }
}
</script>

子组件的代码(即 child.vue):

<template>
  <div>
    <span v-for="(item, index) in list" :key="index">{{item}}</span>
  </div>
</template>
<script>
export default {
  props: ['list'],
}
</script>

2.子组件向父组件传值

$emit 绑定一个自定义事件, 当这个语句被执行时, 就会将参数 arg 传递给父组件,父组件通过 v-on 监听并接收参数。

父组件的代码:

<template>
  <div class="section">
    <child :list="list"  @onEmitIndex="onEmitIndex"></child>
    <p>{{currentIndex}}</p>
  </div>
</template>
<script>
import child from './child.vue'
export default {
  components: { child },
  data() {
    return {
      currentIndex: -1,
      list: ['a1', 'b2', 'c3']
    }
  },
  methods: {
    onEmitIndex(idx) {
      this.currentIndex = idx
    }
  }
}
</script>

子组件的代码(即 child.vue):

<template>
  <div>
    <span v-for="(item, index) in list" :key="index" @click="emitIndex(index)">{{item}}</span>
  </div>
</template>
<script>
export default {
  props: ['list'],
  methods: {
    emitIndex(index) {
      this.$emit('onEmitIndex', index)
    }
  }
}
</script>

二、ref/refs

ref 如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据。也算是子组件向父组件传值的一种。

父组件 parent.vue:

<template>
  <child ref="childForRef"></child>
</template>
<script>
import child from './child.vue'
  export default {
    components: { child },
    mounted() {
      const childForRef = this.$refs.childForRef;
      console.log(childForRef.name);
      childForRef.sayHello();
    }
  }
</script>

子组件 child.vue:

export default {
  data () {
    return {
      name: 'Vue.js'
    }
  },
  methods: {
    sayHello () {
      console.log('hello')
    }
  }
}

三、eventBus

**eventBus **又称为事件总线,在 vue 中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。一般用来兄弟组件和隔代组件传值。
1 首先需要创建一个事件总线并将其导出, 以便其他模块可以使用或者监听它。
bus.js:

import Vue from 'vue'
export const bus = new Vue()

2 发送事件,假设有 child1、child2 两个兄弟组件,在 child1.vue 中发送事件。
parent.vue:

<template>
  <div>
    <child1></child1>
    <child2></child2>
  </div>
</template>
<script>
import child1 from './child1.vue'
import child2 from './child2.vue'
export default {
  components: { child1, child2 }
}
</script>

child1.vue:

<template>
  <div>
    <button @click="additionHandle">+加法器</button>    
  </div>
</template>
<script>
import {bus} from '@/bus.js'
console.log(bus)
export default {
  data(){
    return{
      num:1
    }
  },
  methods:{
    additionHandle(){
      bus.$emit('addition', {
        num:this.num++
      })
    }
  }
}
</script>

在 child2.vue 中接收事件。

<template>
  <div>计算和: {{count}}</div>
</template>
<script>
import { bus } from '@/bus.js'
export default {
  data() {
    return {
      count: 0
    }
  },
  mounted() {
    bus.$on('addition', arg=> {
      this.count = this.count + arg.num;
    })
  }
}
</script>

4.如果想移除事件的监听, 可以像下面这样操作:

import { bus } from './bus.js'
Bus.$off('addition', {})

四、Vuex

父组件:

<template>
  <div id="app">
    <ChildA/>
    <ChildB/>
  </div>
</template>

<script>
  import ChildA from './ChildA' // 导入A组件
  import ChildB from './ChildB' // 导入B组件

  export default {
    name: 'App',
    components: {ChildA, ChildB} // 注册A、B组件
  }
</script>

子组件childA:

<template>
 <div id="childA">
   <h1>我是A组件</h1>
   <button @click="transform">点我让B组件接收到数据</button>
   <p>因为你点了B,所以我的信息发生了变化:{{BMessage}}</p>
 </div>
</template>

<script>
 export default {
   data() {
     return {
       AMessage: 'Hello,B组件,我是A组件'
     }
   },
   computed: {
     BMessage() {
       // 这里存储从store里获取的B组件的数据
       return this.$store.state.BMsg
     }
   },
   methods: {
     transform() {
       // 触发receiveAMsg,将A组件的数据存放到store里去
       this.$store.commit('receiveAMsg', {
         AMsg: this.AMessage
       })
     }
   }
 }
</script>

子组件 childB:

<template>
 <div id="childB">
   <h1>我是B组件</h1>
   <button @click="transform">点我让A组件接收到数据</button>
   <p>因为你点了A,所以我的信息发生了变化:{{AMessage}}</p>
 </div>
</template>

<script>
 export default {
   data() {
     return {
       BMessage: 'Hello,A组件,我是B组件'
     }
   },
   computed: {
     AMessage() {
       // 这里存储从store里获取的A组件的数据
       return this.$store.state.AMsg
     }
   },
   methods: {
     transform() {
       // 触发receiveBMsg,将B组件的数据存放到store里去
       this.$store.commit('receiveBMsg', {
         BMsg: this.BMessage
       })
     }
   }
 }
</script>

vuex的 store.js

import Vue from 'vue'
 import Vuex from 'vuex'
 Vue.use(Vuex)
 const state = {
   // 初始化A和B组件的数据,等待获取
   AMsg: '',
   BMsg: ''
 }
 
 const mutations = {
   receiveAMsg(state, payload) {
     // 将A组件的数据存放于state
     state.AMsg = payload.AMsg
   },
   receiveBMsg(state, payload) {
     // 将B组件的数据存放于state
     state.BMsg = payload.BMsg
   }
 }
 
 export default new Vuex.Store({
   state,
   mutations
 })

然后需要在 main.js 中引入 vuex

import Vue from 'vue'
import App from './App'
import router from './router'
import store from './store';

Vue.config.productionTip = false

new Vue({
  el: '#app',
  router,
  store,
  components: { App },
  template: '<App/>'
})

五、$attrs/$listeners

parent.vue:

<template>
  <div>
    <child-a :name="name" :age="age" :gender="gender" :height="height" title="嘿嘿嘿"></child-a>
  </div>
</template>
<script>
import ChildA from './ChildA'
export default {
  components: { ChildA },
  data() {
    return {
      name: "zhang",
      age: "18",
      gender: "女",
      height: "168"
    };
  }
};
</script>

// childCom1.vue

<template class="border">
  <div>
    <p>name: {{ name}}</p>
    <p>childCom1的$attrs: {{ $attrs }}</p>
    <child-com2 v-bind="$attrs"></child-com2>
  </div>
</template>
<script>
const childCom2 = () => import("./childCom2.vue");
export default {
  components: {
    childCom2
  },
  inheritAttrs: false, // 可以关闭自动挂载到组件根元素上的没有在props声明的属性
  props: {
    name: String // name作为props属性绑定
  },
  created() {
    console.log(this.$attrs);
     // { "age": "18", "gender": "女", "height": "158", "title": "程序员成长指北" }
  }
};
</script>

// childCom2.vue

<template>
  <div class="border">
    <p>age: {{ age}}</p>
    <p>childCom2: {{ $attrs }}</p>
  </div>
</template>
<script>

export default {
  inheritAttrs: false,
  props: {
    age: String
  },
  created() {
    console.log(this.$attrs); 
    // { "gender": "女", "height": "158", "title": "程序员成长指北" }
  }
};
</script>

六、$children/$parent

parent.vue:

 <template>
  <div>
    <div>{{msg}}</div>
    <child></child>
    <button @click="changeA">点击改变子组件值</button>
  </div>
</template>

<script>
import Child from './child'
export default {
  components: { Child },
  data() {
    return {
      msg: 'Welcome'
    }
  },

  methods: {
    changeA() {
      this.$children[0].messageA = 'this is new value'
    }
  }
}
</script>

child.vue:

<template>
  <div class="com_a">
    <span>{{messageA}}</span>
    <p>获取父组件的值为:  {{parentVal}}</p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      messageA: 'this is old'
    }
  },
  computed:{
    parentVal(){
      return this.$parent.msg;
    }
  }
}
</script>

要注意边界情况,如在 #app 上拿 $parent 得到的是 new Vue() 的实例,在这实例上再拿 $parent 得到的是 undefined,而在最底层的子组件拿 $children 是个空数组。也要注意得到 $parent 和 $children 的值不一样,$children 的值是数组,而 $parent 是个对象。

标签:Vue,六种,default,vue,export,child,组件,import,传值
From: https://www.cnblogs.com/liliuyu/p/13590853.html

相关文章

  • vue 实现文件切片上传
    在实际开发项目过程中有时候需要上传比较大的文件,然后呢,上传的时候相对来说就会慢一些,so,后台可能会要求前端进行文件切片上传,很简单哈,就是把比如说1个G的文件流切割成若干个小的文件流,然后分别请求接口传递这个小的文件流。流程简说实现文件切片导入,首先我们使用elementUI也好,......
  • 【开源】基于Vue.js的高校实验室管理系统
    一、摘要1.1项目介绍开放实验室管理系统包含实验室类型模块、实验室档案模块、实验模块、实验设备模块、实验订单模块,还包含系统自带的用户管理、部门管理、角色管理、菜单管理、日志管理、数据字典管理、文件管理、图表展示等基础模块,开放实验室管理系统基于角色的访问控制,给学生......
  • vue3 父组件传值给子组件 子组件修改后回传给父组件
    父组件<jdy-goods-attrv-model:goods_sn="goods.goods_sn"></jdy-goods-attr>//尤总在vue3的时候给我们提供了一个新的思路:v-model来实现父传子,并且子也可以修改父组件传递过来的数据。子组件constprops=defineProps({goods_sn:{type:String,default:'......
  • vue3 子组件修改父组件的两种方法
    <jdy-goods-attr:goods_sn="goods.goods_sn"@goods_sn="(msg)=>goods.goods_sn=msg"v-model:goods_num="goods.goods_num"></jdy-goods-attr>constemit=defineEmits(['goods_sn',�......
  • vue-大文件分片及断点上传
    最近开发过程中,有一个大文件分片上传的功能,借鉴于网上的思路,结合自己后端的逻辑,完成了这个功能,在此记录如下:界面展示:    一、将大文件分片上传写为一个组件,可以全局注册该组件,也可以在使用的页面注册该组件,使用vuex通讯进行组件间传值由于我有好几个页面需要使用大文......
  • Vue轻量级富文本编辑器-Vue-Quill-Editor
    先看效果图:女神镇楼1.下载Vue-Quill-Editornpminstallvue-quill-editor--save2.下载quill(Vue-Quill-Editor需要依赖)npminstallquill--save3.代码<template><divclass="edit_container"><quill-editorv-model="cont......
  • Vue 2.x脱坑记-查漏补缺
    Q:组件的通讯有哪几种啊!基本最常用的是这三种;父传子: props子传父: emit兄弟通讯:eventbus:就是找一个中间组件来作为信息传递中介vuex:信息树传送门:基本通讯VuexQ:为什么我的 npm 或者 yarn 安装依赖会生成 lock文件,有什么用!lock文件的作用......
  • vue~封装一个文本框标签组件
    用到的技术父组件向子组件的传值类型检查和默认值:您可以为props指定类型检查和默认值。这可以确保传递给子组件的数据符合期望的类型,以及在没有传递数据时具有合理的默认值。例如:props:{message:{type:String,default:'DefaultMessage'},count:{typ......
  • vue~封装一个文本框添加与删除的组件
    标签组件的效果如下组件作用这是一个div,包含了两个文本框,后面是添加和删除按钮添加按钮复制出新的div,除了文本框没有内容,其它都上面一样删除按钮将当前行div删除组件实现<template><div><templatev-for="(item,index)intags"><el-row:gutter="4"style="margin:......
  • Vue双向数据绑定原理-上
    Vue响应式的原理(数据改变界面就会改变)是什么?时时监听数据变化,一旦数据发生变化就更新界面,这就是Vue响应式的原理。Vue是如何实现时时监听数据变化的通过原生JS的defineProperty方法,通过get和set方法来监听数据的变化。defineProperty方法的特点可以直接在一个对象上定义一......