前期写项目时,无论项目大小,都是用的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>
前端页面上显示的内容:
梳理一下逻辑:
msg的值是: {{ msg }}
以上就是父组件向子组件传值的全过程,核心要点是——使用自定义属性
的确比vuex简单得多,但是需要注意的是:不要直接修改props中的值
示例:
在子组件的页面中添加一个按钮:
这种写法虽然不报错,但是控制台会警告,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>
几个要点:
子组件中要做的事情已经做完,现在看看父组件是如何在接收数据的
父组件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>
同样几个要点:
看下页面上显示的东西:
原则:使用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)
}
}
要点:
再来看看接收数据的组件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
})
}
要点:
看看页面上的内容
这个兄弟组件的数据共享可以理解成:
至此,简单的组件之间的数据共享已经全部实现,不过个人还是倾向于使用vuex传值,可能是先入为主了,作为一种备选方案保留吧。