父子组件传值
1:父组件向子组件传值
分析:父组件向子组件传值直接在调用子组件的地方v-bind:[子组件属性],子组件通过props就可以接受到父组件传过来的值了
父组件:Father.vue
<template>
<div>
<Child :text="text"></Child>
</div>
</template>
<script>
import Child from './components/Child'
export default {
name: "list",
data(){
return{
text:'我是父组件传过来的值'
}
},
components:{
Child
}
}
</script>
子组件:Child.vue
<template>
<div>
父组件传过来的值:
<span>{{text}}</span>
</div>
</template>
<script>
export default {
name: "chuanzhi",
props:['text'],//接受父组件传过来的值
data(){
return{
}
},
}
</script>
2:子组件向父组件传值
分析:子组件向父组件传值,要借用vue. e m i t 这 个 方 法 添 加 一 个 监 听 器 , 然 后 在 父 组 件 捕 获 该 事 件 v u e . emit这个方法添加一个监听器,然后在父组件捕获该事件 vue. emit这个方法添加一个监听器,然后在父组件捕获该事件vue.emit(eventName,data)方法接受2个参数 eventName:监听器的名字,data:需要告诉父组件的数据
父组件:Father.vue
<template>
<div>
//通过v-on + 子组件emit定义的eventName这里是childEmit + 父组件监听的回调这里是fatherEmit
<Child :text="text" v-on:childEmit="fatherEmit"></Child>
</div>
</template>
<script>
import Child from './components/Child'
export default {
name: "list",
data(){
return{
text:'我是父组件传过来的值'
}
},
components:{
Child
},
methods:{
fatherEmit(text){
console.log(text) //这是儿子要跟老子说的悄悄话
},
}
}
</script>
子组件:child.vue
<template>
<div>
父组件传过来的值:
<span>{{text}}</span>
</div>
</template>
<script>
export default {
name: "chuanzhi",
props:['text'],
data(){
return{
}
},
mounted() {
//这里是划重点
this.$emit('childEmit',"这是儿子要跟老子说的悄悄话");
}
}
</script>
3:兄弟组件、一点关系都没有的组件的数据之间传递
解析:对于这种组件之间的传值有一下几种解决方法
1:数据共享比较少的可以采用网上比较流行的bus.js的方法或是Vue-observable
2:对于数据共享比较多的可以用vuex作为公共仓库
这两种方法跟你直接存本地缓存(localStorage)然后再去取有一个最主要的区别就是存在本地的缓存的数据变化之后vue是追踪不到属性值的变化的所以view视图层也是不会有更新的,但是通过bus、Vue-observable、vuex、emit等方法,属性值改变之后vue也可以实时的渲染页面。下面就开始解析一下这几种写法
bus.js方法
bus方法也是通过vue.$emit方法去实现的,下面是代码实现
bus.js文件
import Vue from 'vue';
export default new Vue();
父组件:father.vue
<template>
<div>
<Didi></Didi>
<Gege></Gege>
</div>
</template>
<script>
import Didi from './components/didi'
import Gege from './components/gege'
import bus from './config/bus.js'
export default {
name: "list",
data(){
return{
text:'我是父组件传过来的值'
}
},
components:{
Didi,
Gege
},
mounted(){
bus.$on('gege',(msg)=>{
console.log("我是爸爸,我听到哥哥跟弟弟说",msg)
});
bus.$on('didi',(msg)=>{
console.log("我是爸爸,我听到弟弟跟哥哥说",msg)
});
},
}
didi.vue组件
<template>
<button class="brother" @click="didi" >我是弟弟</button>
</template>
<script>
import bus from '@/config/bus.js'
export default {
name: "didi",
mounted(){
bus.$on('gege',(msg) =>{
console.log("弟弟监听哥哥说的话",msg)
});
},
methods:{
didi(){
bus.$emit('didi','我是弟弟');
}
},
}
</script>
gege.vue组件
<template>
<button class="brother" @click="gege">我是哥哥</button>
</template>
<script>
import bus from '@/config/bus.js'
export default {
name: "gege",
props:['data'],
mounted(){
bus.$on('didi',(msg) =>{
console.log("哥哥监听弟弟说的话",msg)
});
bus.$emit('gege','我是哥哥');
},
methods:{
gege(){
bus.$emit('gege','我是哥哥');
}
}
}
</script>
因为忘记截图效果图了,就用文字描述吧
当点击didi.vue这个组件时候
控制台会输出:我是爸爸,我听到弟弟跟哥哥说 我是弟弟
哥哥监听弟弟说的话 我是弟弟
当点击gege.vue这个组件的时候
控制台输出:我是爸爸,我听到哥哥跟弟弟说 我是哥哥
弟弟监听哥哥说的话 我是哥哥
首先有几点是需要注意的就是
1:触发emit事件的时候,你监听的函数不能位于触发之后必须要在触发之前
vm.$emit('test', 'hi')
vm.$on('test', function (msg) {
console.log(msg)
})
//这种是监听不到emit的数据的,因为触发emit事件的时候还未添加监听
<------------------分割线------------------------>
vm.$on('test', function (msg) {
console.log(msg)
})
vm.$emit('test', 'hi')
//这种就可以监听到emit
2:就是father.vue、gege.vue、didi.vue三个文件必须都要引入bug.js文件,bug相当于一个中介作用
接下来介绍今天的重头戏Vue-observable
Vue-observable方法
先贴一波官网的介绍
简单的来说就是observable()方法可以帮你监听data里面的属性的变化,然后你需要的时候就可以去他这里面取出来我把它理解为一个小型的vuex
下面贴一下实际使用场景的代码
定义一个store.js来存储变量,方便管理
import Vue from 'vue';
export let store =Vue.observable({count:0}); //count即是observable帮我们监听的属性
father.vue组件
<template>
<div>
<button @click="stop">改变count</button>
<h3>{{count}}</h3>
<Child></Child>
</div>
</template>
<script>
import {store} from '@/config/store.js'
import Child from '@/components/Child.vue'
export default {
name: "list",
data(){
return{
text:'我是父组件传过来的值'
}
},
computed:{
count(){
//记住store定义的属性必须写在computed里面页面才会实时渲染,否则数据改变了,页面还是不响应的
return store.count
}
},
components:{
Child
},
methods:{
stop:function () {
store.count = 100;
}
},
}
</script>
Child.vue组件
<template>
<div>
<span>改变后子组件接受到的count{{count}}</span>
</div>
</template>
<script>
import {store} from '@/config/store.js'
export default {
name: "chuanzhi",
computed:{
count(){
return store.count
}
},
}
</script>
效果图:
点击前:
点击后:
最后补充一点,就是如果当前项目vue版本低于2.6,要使用Vue.observable(),就必须要升级,升级 vue 和 vue-template-compiler,两者的版本需要同步,如果不同步项目会报错。
然后写到这里,文章的篇幅已经有点长了,Vuex的话等下一次在起一篇文章更新吧,然后这篇文章希望可以帮助到你们解决组件之间的传值问题,由于是第一次写文章,所以表述不是特别清楚,我已经尽量用代码去表达了,此文章如果有什么错的也请大家指出了,我一定纠正