• vue2通信方法(最全)


    前言

    数据传递是框架的核心要素之一,也是在业务开发中极其重要的技术.熟练掌握所有的通信方法,是开发者必须具备的技能。

    这篇文章我将会把vue2所有的通信的方法都形成简单易懂的demo。

    在我的分类中,通信方法有两种大类型:

    1.vue框架提供的通信方法

    2.插件及其他通信方法

    一.vue框架提供的通信方法:

    1.props通信

    props通信方法可以实现父组件向子组件传递参数,也可以实现子组件给父组件传递参数.

    父传子:传递常规变量

    子传父:传递函数

    父组件
    1. <template>
    2. <div>
    3. <p>父组件数字值1:{{ numValue1 }} <el-button @click="addNum">增加el-button>p>
    4. <p>获取子组件的值:{{ numValue2 }}el-button>p>
    5. <hr />
    6. <PropsChild :numValue1="numValue1" :numValue2="getChildValue">PropsChild>
    7. div>
    8. template>
    9. <script>
    10. import PropsChild from './child.vue'
    11. export default {
    12. name: 'propsTest',
    13. components: {
    14. PropsChild
    15. },
    16. data() {
    17. return {
    18. numValue1: 0,
    19. numValue2: '父组件默认的值'
    20. }
    21. },
    22. methods: {
    23. addNum() {
    24. this.numValue1++
    25. },
    26. getChildValue(childValue) {
    27. console.log(childValue, '???子组件的数值')
    28. this.numValue2 = childValue
    29. },
    30. getChildValueFun() {
    31. }
    32. }
    33. }
    34. script>
    35. <style lang="less">style>
    子组件
    1. <template>
    2. <div>
    3. 子组件
    4. <el-input v-model="value" @input="changeValue">el-input>
    5. div>
    6. template>
    7. <script>
    8. export default{
    9. name:'emitChild',
    10. data(){
    11. return{
    12. value:'子组件默认的值'
    13. }
    14. },
    15. methods:{
    16. changeValue(){
    17. this.$emit('getChildValue',this.value)
    18. }
    19. }
    20. }
    21. script>
    22. <style lang="less">
    23. style>
    效果:

    2.emit通信(自定义事件)

    父组件
    1. <template>
    2. <div>
    3. 父组件
    4. <el-input v-model="value">el-input>
    5. <hr>
    6. <EmitChild @getChildValue="getChildValue">EmitChild>
    7. div>
    8. template>
    9. <script>
    10. import EmitChild from './child.vue'
    11. export default{
    12. name:'emitTest',
    13. data(){
    14. return{
    15. value:'父组件默认的值'
    16. }
    17. },
    18. components:{
    19. EmitChild
    20. },
    21. methods:{
    22. getChildValue(childValue){
    23. this.value = childValue
    24. }
    25. }
    26. }
    27. script>
    28. <style lang="less">
    29. style>
    子组件
    1. <template>
    2. <div>
    3. 子组件
    4. <el-input v-model="value" @input="changeValue">el-input>
    5. div>
    6. template>
    7. <script>
    8. export default{
    9. name:'emitChild',
    10. data(){
    11. return{
    12. value:'子组件默认的值'
    13. }
    14. },
    15. methods:{
    16. changeValue(){
    17. this.$emit('getChildValue',this.value)
    18. }
    19. }
    20. }
    21. script>
    22. <style lang="less">
    23. style>
    效果

    3.evenBus(全局事件总线) 

    main.js安装事件总线

    1. new Vue({
    2. router,
    3. store,
    4. axios,
    5. //配置事件总线
    6. beforeCreate(){
    7. Vue.prototype.$bus = this
    8. },
    9. render: h => h(App),
    10. }).$mount('#app')
    任意组件1:
    1. <template>
    2. <div>
    3. <p>子组件1p>
    4. <p>子组件1的值:{{ value1 }} <el-button @click="addNum">增加el-button>p>
    5. <p>来自子组件2的值:{{ value2 }}p>
    6. div>
    7. template>
    8. <script>
    9. export default{
    10. name:'child1',
    11. data(){
    12. return{
    13. value1:0,
    14. value2:100
    15. }
    16. },
    17. created(){
    18. this.$eventBus.$on('bus_deleteNum',this.changeValue2)
    19. },
    20. methods:{
    21. addNum(){
    22. this.value1++
    23. this.$eventBus.$emit('bus_addNum',this.value1)
    24. },
    25. changeValue2(val){
    26. this.value2 = val
    27. }
    28. },
    29. destroyed(){
    30. this.$eventBus.$off('bus_deleteNum')
    31. }
    32. }
    33. script>
    任意组件2
    1. <template>
    2. <div>
    3. 子组件2
    4. <p>来自子组件1的值:{{ value1 }}p>
    5. <p>子组件2的值:{{ value2 }} <el-button @click="deleteNum">减少el-button> p>
    6. div>
    7. template>
    8. <script>
    9. export default{
    10. name:'child2',
    11. data(){
    12. return{
    13. value1:0,
    14. value2:100
    15. }
    16. },
    17. created(){
    18. this.$eventBus.$on('bus_addNum',this.changeValue1)
    19. },
    20. methods:{
    21. changeValue1(value){
    22. this.value1 = value
    23. },
    24. deleteNum(){
    25. this.value2--
    26. this.$eventBus.$emit('bus_deleteNum',this.value2)
    27. }
    28. },
    29. destroyed(){
    30. this.$eventBus.$off('bus_addNum')
    31. }
    32. }
    33. script>
    效果

     4.ref通信

    父组件
    1. <template>
    2. <div>
    3. <p>父组件的值:{{ value }} <el-button @click="addNum">增加el-button> p>
    4. <hr>
    5. <Child ref="child">Child>
    6. div>
    7. template>
    8. <script>
    9. import Child from './child.vue'
    10. export default{
    11. name:'refTest',
    12. components:{
    13. Child
    14. },
    15. data(){
    16. return{
    17. value:0
    18. }
    19. },
    20. methods:{
    21. addNum(){
    22. this.value++
    23. this.$refs.child.getValue(this.value)
    24. }
    25. }
    26. }
    27. script>
    子组件
    1. <template>
    2. <div>
    3. 子组件的值{{ value }}
    4. div>
    5. template>
    6. <script>
    7. export default{
    8. name:'refTest',
    9. data(){
    10. return{
    11. value:'子组件初始化的值'
    12. }
    13. },
    14. methods:{
    15. getValue(val){
    16. this.value = val
    17. }
    18. }
    19. }
    20. script>
    效果

     5.组件v-model通信

     v-model不仅可以在输入类型标签上实现双向数据绑定,也可以在组件上实现父子组件数据通信

    父组件
    1. <template>
    2. <div>
    3. <el-input v-model="value">el-input>
    4. <hr />
    5. <Child v-model="value" @changeValue="changeValue">Child>
    6. div>
    7. template>
    8. <script>
    9. import Child from "./child.vue";
    10. export default {
    11. name: "vModel",
    12. components: {
    13. Child,
    14. },
    15. data() {
    16. return {
    17. value: "父组件默认的值",
    18. };
    19. },
    20. methods: {
    21. changeValue(data) {
    22. this.value = data;
    23. },
    24. },
    25. };
    26. script>
    子组件
    1. <template>
    2. <div>
    3. 子组件
    4. <el-input v-model="inputvalue" @input="changeValue">el-input>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. name: "child",
    10. props: ["value"],
    11. model: {
    12. prop: "value",
    13. event: "changeValue",
    14. },
    15. data() {
    16. return {
    17. inputvalue: "子组件默认的值",
    18. };
    19. },
    20. create() {
    21. //子组件初始化同步,注释掉则为默认值
    22. // this.inputvalue = this.value;
    23. },
    24. methods: {
    25. changeValue(val) {
    26. this.$emit("changeValue", val);
    27. },
    28. },
    29. watch: {
    30. value: function (newVal) {
    31. this.inputvalue = newVal;
    32. },
    33. },
    34. };
    35. script>
     效果

    父子组件数据同步

    6.sync修饰符通信

    sync修饰符也是一种语法糖,也可以实现父子通信

    父组件
    1. <template>
    2. <div>
    3. <div>sync模块div>
    4. <el-input v-model="value">el-input>
    5. <hr />
    6. <Child :value.sync="value" @changeVal="changeVal">Child>
    7. div>
    8. template>
    9. <script>
    10. import Child from "./child.vue";
    11. export default {
    12. name: "sync",
    13. components: {
    14. Child,
    15. },
    16. data() {
    17. return {
    18. value: "父组件默认的值",
    19. };
    20. },
    21. methods: {
    22. changeVal(val) {
    23. this.value = val;
    24. },
    25. },
    26. };
    27. script>
    28. <style lang="less" scoped>
    29. style>
    子组件
    1. <template>
    2. <div>
    3. <p>子组件p>
    4. <el-input v-model="childValue" @input="changeVal">el-input>
    5. div>
    6. template>
    7. <script>
    8. export default {
    9. name: "child",
    10. props: ["value"],
    11. data() {
    12. return {
    13. childValue: "子组件默认的值",
    14. };
    15. },
    16. methods: {
    17. changeVal() {
    18. this.$emit("changeVal", this.childValue);
    19. },
    20. },
    21. watch: {
    22. value: function (newVal) {
    23. this.childValue = newVal;
    24. },
    25. },
    26. };
    27. script>
    28. <style lang="less" scoped>
    29. style>
    效果

    7.$attr 和 $listeners

    父组件
    1. <template>
    2. <div>
    3. <p>$attrs与$listenersp>
    4. <p>title的值:<el-input class="inputBox" v-model="title">el-input>p>
    5. <p>数值1:<el-input class="inputBox" v-model="value1">el-input>p>
    6. <p>数值2:<el-input class="inputBox" v-model="value2.value">el-input>p>
    7. <p>数字值:{{ num }}p>
    8. <hr />
    9. <Child
    10. :title="title"
    11. :value1="value1"
    12. :value2="value2"
    13. v-on="$listeners"
    14. @changeNum="changeNum"
    15. >Child>
    16. div>
    17. template>
    18. <script>
    19. import Child from "./child.vue";
    20. export default {
    21. name: "AttrListen",
    22. components: {
    23. Child,
    24. },
    25. data() {
    26. return {
    27. title: "标题",
    28. value1: "数值1",
    29. value2: {
    30. value: "对象字段2",
    31. },
    32. num: 0,
    33. };
    34. },
    35. mounted() {},
    36. methods: {
    37. changeNum() {
    38. this.num++;
    39. },
    40. },
    41. };
    42. script>
    43. <style lang="less" scoped>
    44. .inputBox {
    45. width: 300px;
    46. }
    47. style>
    子组件
    1. <template>
    2. <div>
    3. <p>子组件p>
    4. <p>title的值:{{ $attrs.title }}p>
    5. <p>数值1:{{ $attrs.value1 }}p>
    6. <p>数值2:{{ $attrs.value2.value }}p>
    7. <el-button @click="changeNum">修改值el-button>
    8. div>
    9. template>
    10. <script>
    11. export default {
    12. name: "child",
    13. created() {},
    14. methods: {
    15. changeNum() {
    16. console.log(this.$listeners, "this.$listeners的值子组件");
    17. // this.$emit("changeNum");
    18. this.$listeners.changeNum();
    19. },
    20. },
    21. };
    22. script>
    23. <style lang="less" scoped>
    24. style>
    效果

    8. provide和inject

    可以实现上层组件对于后代组件的值传递,相当于穿透传递

    祖先组件(这里使用app.vue)
    1. <template>
    2. <div id="app">
    3. <router-view>router-view> div>
    4. template>
    5. <script>
    6. export default {
    7. name: 'App',
    8. provide(){
    9. return{
    10. penetrateVal:'穿透的值'
    11. }
    12. },
    13. components: {
    14. },
    15. created(){
    16. },
    17. methods:{
    18. }
    19. }
    20. script>
    任意后代组件
    1. <template>
    2. <div>
    3. <p>穿透值:{{ penetrateVal }}p>
    4. div>
    5. template>
    6. <script>
    7. export default {
    8. name: 'prodvideAndInject',
    9. inject: ['penetrateVal'],
    10. methods: {
    11. }
    12. }
    13. script>
    14. <style>style>
    效果

     9.作用域插槽

    父组件
    1. <template>
    2. <div>
    3. 父组件
    4. <hr>
    5. <Child>
    6. <template slot-scope="num">
    7. <span>父组件中使用:{{ num.data }}span>
    8. template>
    9. Child>
    10. div>
    11. template>
    12. <script>
    13. import Child from './child.vue'
    14. export default {
    15. name: 'slotVal',
    16. components: {
    17. Child
    18. },
    19. }
    20. script>
    子组件
    1. <template>
    2. <div>
    3. <slot :data="num">slot>
    4. <el-button @click="add">子组件中点击增加el-button>
    5. div>
    6. template>
    7. <script>
    8. export default{
    9. name:'Child',
    10. data(){
    11. return{
    12. num:0
    13. }
    14. },
    15. methods:{
    16. add(){
    17. this.num ++
    18. }
    19. }
    20. }
    21. script>
    效果

     以上都是vue框架自带的通信方法,但是在开发业务中是不够用的,因为还需要有一些全局的通信方法,去实现业务逻辑。

    二.插件和其他的通信方法

    这里的一些方法就不写具体的demo和效果图了,只是做一个简单的介绍

    1.vue-router

    路由传参是实现参数传递的重要途径,想必是个vue开发者肯定都用过吧

    传递方
    this.$router.push({path:'/demo1',query:{id:1}})
    接收方
    console.log(this.$route.query.id)

    2.vuex

    这里也不细说,绝大多数vue2的项目都用vuex来做全局的一个参数存储,例如用户信息,token等等,都离不开vuex

    vuex地址:Vuex 是什么? | Vuex

    3.Pinia

    本质是和vuex是一样的,不过做了优化,在vue3项目中会使用的更多,也可以在vue2中使用

    pinia地址:介绍 | Pinia 中文文档

    4.Storage

    这里是对localStroage和sessionStorage的统称,这两个都是浏览器本身的方法,都具有持久化保存的作用。最具体的就是用户token校验,判断是否登录过的时候,基本都得用Storage。

    5.cookie

    和Storage差不多的东西,不细说

    6.redux

    默认是react的配套插件,虽然没见过什么大神在vue中用redux,但是官方介绍确实可以在vue中使用redux。

    我是没有操作过,想看的可以参考引用其他人的文档:Redux vue - 老白网络

     7.PubSub(万金油)

    镇场子的大哥,任何框架,甚至原生都可以使用的一个经典信息传递插件,设计模式的经典之作,跨越语言的存在,别说前端了,你在redis上也都会遇到pubsub.

    在使用上和eventbus像,简单好用。我就不费劲写了,直接参考别人的文档吧:一、PubSub 的Vue使用方式_vue pubsub-CSDN博客

    结束语

    方法有很多,但具体如何使用,看场景,看业务,灵活变通。

    其实,不只是props可以实现双向传递参数,$emit和ref都是可以的,你只需要换个思路就可以了,我这里还写了一篇拓展:,使用props,emit和ref实现双向数据通信。

    有兴趣的可以去看看:vue2组件通信中的一些拓展(props,emit,ref父子双向传参)-CSDN博客

  • 相关阅读:
    【学习笔记】C++再入门过程-2
    2007-2021年31省市财政环保支出占比数据(含原始数据+计算过程+测算结果)
    008. 子集
    Ubuntu如何连接WiFi
    【UiPath2022+C#】UiPath 调试
    (rabbitmq的高级特性)消息可靠性
    DDoS攻击的工具介绍
    Python(一)——简介与Windows平台安装
    Spring注解驱动之FactoryBean注册组件
    搭建confluence
  • 原文地址:https://blog.csdn.net/m0_54741495/article/details/134395355