vue组件之间的数据共享

发布于:2022-11-28 ⋅ 阅读:(341) ⋅ 点赞:(0)

vue组件之间的数据共享

前期写项目时,无论项目大小,都是用的vuex来实现的数据共享,随着学习的深入,发现使用vuex有点大材小用了。一般情况下,vuex适合大型项目、组件结构复杂的项目实现数据共享,vuex无视组件的父子、兄弟关系,只要在store中进行了注册,所有的组件都可以共享,但是也会存在一些问题,比如刷新页面会导致一些信息丢失的问题,虽然能解决,但也挺麻烦。通过学习,了解了更简单的组件间传递数据的方法,记录一下。

父向子传值

原则:父组件向子组件共享数据需要使用自定义属性

子组件Left.vue:

<template>
    <div class="left-container">
        <h3>Left组件</h3>
        <p>msg的值是: {{ msg }}</p>
        <p>user的值是: {{user}}</p>
    </div>
</template>

<script>
export default {
    props: ['msg', 'user']

}
</script>

<style lang="less">
.left-container {
    padding: 0 20px 20px;
    background-color: orange;
    min-height: 250px;
    flex: 1;
}
</style>

父组件App.vue:

<template>
  <div id="app">
    <h1>App根组件</h1>
    <hr />
    <div class="box">
      <Left :msg="message" :user="userinfo"></Left>
    </div>
  </div>
</template>

<script>
import Left from '@/components/Left.vue'

export default {
 data() {
  return {
    message: '我是父组件',
    userinfo: {name: 'wsc', age: 18}
  }
 },
 components: {
  Left,
 }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

前端页面上显示的内容:

在这里插入图片描述

梳理一下逻辑:

  1. 先写子组件,在子组件中定义自定义属性(props: [‘msg’, ‘user’])
  2. 父组件导入、注册、使用子组件
  3. 父组件在使用子组件时,在标签中使用v-bind向子组件传递子组件中自定义属性并绑定对应的数据<Left :msg="message" :user="userinfo"></Left>
  4. 子组件使用父组件传递过来的数据<p>msg的值是: {{ msg }}</p>

以上就是父组件向子组件传值的全过程,核心要点是——使用自定义属性

的确比vuex简单得多,但是需要注意的是:不要直接修改props中的值

示例:

在子组件的页面中添加一个按钮:

<button @click="msg='abc'">修改msg</button>

这种写法虽然不报错,但是控制台会警告,vue不建议这么操作,正确做法是转存数据,然后修改转存后的数据

子向父传值

原则:子组件向父组件共享数据,使用自定义事件

接着上面的父向子传值的代码写

子组件Right.vue

<template>
    <div class="right-container">
        <h3>Right组件--{{count}}</h3>
        <button @click="add">+1</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            // 子组件的值,要传给父组件App.vue
            count: 0
        }
    },
    methods: {
        add() {
            this.count++
            // 修改数据时,同时通过$emit()发射自定义事件,第一个参数是父组件中的自定义事件名,第二个参数是向父组件传递的值
            this.$emit('numChange', this.count)
        }
    }
}
</script>

<style lang="less">
.right-container {
    padding: 0 20px 20px;
    background-color: lightskyblue;
    min-height: 250px;
    flex: 1
}
</style>

几个要点:

  1. 首先在data中定义一个需要向父组件传递的值count
  2. 通过按钮点击事件使count值发生变化,也就是自增
  3. 在点击按钮改变count值时,同时$emit()发射自定义事件,第一个参数是父组件中的自定义事件名,第二个参数是向父组件传递的值

子组件中要做的事情已经做完,现在看看父组件是如何在接收数据的

父组件App.vue

<template>
  <div id="app" class="app-container">
    <h1>App根组件--{{countFromRight}}</h1>
    <hr />
    <div class="box">
      <Left :msg="message" :user="userinfo"></Left>
      <Right @numChange="getNewCount"></Right>
    </div>
  </div>
</template>

<script>
import Left from '@/components/Left.vue'
import Right from '@/components/Right.vue'

export default {
  data() {
    return {
      message: '我是父组件',
      userinfo: { name: 'wsc', age: 18 },
      // 接收子组件传递过来的数据
      countFromRight: 0
    }
  },
  components: {
    Left,
    Right
  },
  methods: {
    getNewCount(val){
      this.countFromRight = val
    }
  }
}
</script>

<style>
#app {
  padding: 1px 20px 20px;
  background-color: #efefef
}

.box {
  display: flex;
}
</style>

同样几个要点:

  1. 父组件中定义一个值countFromRight,用来接收子组件传递过来的数据
  2. 父组件使用子组件(right标签)时,添加自定义事件,实际上就是子组件中发射的numChange事件(怎么理解这个自定义事件呢,就把它理解为点击事件,和点击事件的逻辑一样的),并为这个自定义事件绑定处理函数getNewCount
  3. 在methods中写自定义事件的处理函数getNewCount,这个函数接收一个参数,也就是子组件传递过来的数据,把这个数据的值赋给countFromRight,这样,在父组件中使用countFromRight就完成了子向父传值的过程

看下页面上显示的东西:

在这里插入图片描述

兄弟组件数据共享

原则:使用EventBus

最重要的一步,新建一个eventBus.js文件,作为兄弟组件之间的桥梁,实现数据共享,这个文件的内容很简单,代码如下:

eventBus.js

import Vue from "vue";

// 向外共享Vue实例对象
export default new Vue()

就两行代码,导入vue,创建vue实例并向外暴露

下面是兄弟组件的代码,发送数据的组件是Left.vue,接收数据的组件是Right.vue

先看发送数据的组件Left.vue

<template>
    <div class="left-container">
        <h3>Left组件</h3>
        <p>msg的值是: {{ msg }}</p>
        <p>user的值是: {{user}}</p>

        <hr />
        <button @click="send">向右侧兄弟组件传递数据</button>
    </div>
</template>

<script>
import bus from './eventBus'
export default {
    props: ['msg', 'user'],
    data() {
        return {
            str: '右边的兄弟你好'
        }
    },
    methods: {
        send() {
            bus.$emit('share', this.str)
        }
    }

}
</script>

<style lang="less">
.left-container {
    padding: 0 20px 20px;
    background-color: orange;
    min-height: 250px;
    flex: 1;
}
</style>

相关的代码如下:

<button @click="send">向右侧兄弟组件传递数据</button>
data() {
        return {
            str: '右边的兄弟你好'
        }
    },
methods: {
        send() {
            bus.$emit('share', this.str)
        }
    }

要点:

  1. 定义需要发送的数据str
  2. 通过按钮点击事件发送数据
  3. 为按钮点击事件绑定处理函数send
  4. send中通过bus发射自定义时间share,并传递要共享的数据

再来看看接收数据的组件Right.vue

<template>
    <div class="right-container">
        <h3>Right组件--{{count}}</h3>
        <button @click="add">+1</button>
        <hr />
        <p>来自左侧的兄弟组件的数据: {{msgFromLeft}}</p>
    </div>
</template>

<script>
import bus from './eventBus'
export default {
    data() {
        return {
            // 子组件的值,要传给父组件App.vue
            count: 0,
            //  接收来自兄弟组件Left.vue的数据
            msgFromLeft: ''
        }
    },
    methods: {
        add() {
            this.count++
            // 修改数据时,同时通过$emit()发射自定义事件,第一个参数是父组件中的自定义事件名,第二个参数是向父组件传递的值
            this.$emit('numChange', this.count)
        }
    },
    created() {
        bus.$on('share', val=> {
            this.msgFromLeft = val
        })
    }
}
</script>

<style lang="less">
.right-container {
    padding: 0 20px 20px;
    background-color: lightskyblue;
    min-height: 250px;
    flex: 1
}
</style>

相关的代码

<p>来自左侧的兄弟组件的数据: {{msgFromLeft}}</p>
data() {
        return {
            // 子组件的值,要传给父组件App.vue
            count: 0,
            //  接收来自兄弟组件Left.vue的数据
            msgFromLeft: ''
        }
    },
created() {
        bus.$on('share', val=> {
            this.msgFromLeft = val
        })
    }

要点:

  1. data中定义接收数据的变量msgFromLeft
  2. 页面上通过模板语法使用msgFromLeft值
  3. 通过钩子函数created方法,在页面加载之前,就接收数据,接收数据的方式是使用bus.$on()函数来接收,同样也是两个参数,一个是接收的自定义事件名,另一个参数是一个处理函数,函数接收的参数是兄弟组件共享的数据,可以在函数中将这个共享的数据赋值给msgFromLeft
  4. 因为created在加载页面前执行,所以页面上可以直接获取到msgFromLeft的值

看看页面上的内容

在这里插入图片描述

这个兄弟组件的数据共享可以理解成:

  1. bus是父组件
  2. left是子组件,left子组件通过自定义时间将数据发送给bus父组件
  3. bus父组件将接收到的值传递给另一个子组件right

至此,简单的组件之间的数据共享已经全部实现,不过个人还是倾向于使用vuex传值,可能是先入为主了,作为一种备选方案保留吧。

本文含有隐藏内容,请 开通VIP 后查看