d
1.父传子
父组件内容
<template>
<div class="about">
<!-- 基本数据类型 -->
<!-- <Add :ms="msg"></Add> -->
<!-- <Add :msg-val="msgs"></Add> -->
<!-- 引用数据类型 -->
<Add :msg-vals="posts"></Add>
</div>
</template>
<script>
// 两种组件的注册类型:全局注册和局部注册
import Add from "../components/add.vue";
export default {
components: {
Add,
},
data() {
return {
msg: "gg",//【基本数据类型】
msgs:"国剧盛典",
// msgss: [1,2,3],
posts: [
{ id: 1, title: 'My journey with Vue' },
{ id: 2, title: 'Blogging with Vue' },
{ id: 3, title: 'Why Vue is so fun' }
]
};
},
methods: {},
};
</script>
子组件内容
<template>
<div class="button-counte">
<!-- <p>{{ms}}</p> -->
<!-- <p>{{msgVal}}</p> -->
<p v-for="(item,index) in msgVals" :key="index">
{{item.id}} {{item.title}}
</p>
</div>
</template>
<script>
export default {
data(){
return {
}
},
//子组件通过props接收
// props: ['ms'],
// props: ['msgVal'],//需要特别注意,父组件传的是msg-val要将其转化为msgVal(驼峰命名)
props: ['msgVals']
}
</script>
注意:父子组件传值,数据是异步请求,有可能数据渲染时报错:
原因:异步请求时,数据还没有获取到但是此时已经渲染节点了
解决方案:可以在父组件需要传递数据的节点加上 v-if = isReady(isReady默认为false),异步请求获取数据后(isReady赋值为true),v-if = isRead
2.子传父
子组件
<template>
<div class="button-counte">
<!-- 子组件有一个buttton按钮,并为其添加了一个click事件,
当点击的时候使用$emit()触发事件,把 “子-儿子” 这几个字传给父组件。 -->
<button @click="fun()">子传父</button>
</div>
</template>
<script>
export default {
data() {
return {};
},
methods: {
fun() {
// 当点击按钮后,就会执行子组件中的点击事件,
// 然后就会自动触发childEvent自定义事件,
// 然后在触发父组件中的方法,进行相应的操作
//$emit有2个参数:第一个参数为自定义事件,得个参数为要传过去的值
this.$emit("childEvent", "子-儿子");
},
},
};
</script>
父组件
<template>
<div class="about">
<p>{{ textval }}</p>
<!-- 父组件在组件上定义了一个自定义事件childEvent,事件名为parentEvent用于接受子组件传过来的val值 -->
<Add @childEvent="parentEvent"></Add>
</div>
</template>
<script>
// 两种组件的注册类型:全局注册和局部注册
import Add from "../components/add.vue";
export default {
components: {
Add,
},
data() {
return {
textval: "父-父亲",
};
},
methods: {
parentEvent(val) {
//val就是从子组件传过来的值
this.textval = val;
},
},
};
</script>
在子组件中 通过$emit方法传递参数:子组件有一个buttton按钮,并为其添加了一个click事件,当点击的时候使用$emit()触发事件,把 “子-儿子” 这几个字传给父组件。
在父组件中:父组件在组件上定义了一个自定义事件childEvent,事件名为parentEvent用于接受子组件传过来的value值。
3.兄弟传值
Vue 没有直接子对子传参的方法,建议将需要传递数据的子组件,都合并为一个组件。如果一定需要子对子传参,可以先从传到父组件,再传到子组件。
或者通过eventBus或vuex(小项目少页面用eventBus,大项目多页面使用 vuex)传值:
这里具体说的是通过事件总线来传值:
大致实现方法:
var Event = new Vue(); //中心事件的调度剂
Event.$emit(事件名,数据); 触发当前实例上的事件,并传一个参数
Event.$on(事件名,回调函数); 监听event事件后运行 */
//$emit 相当于一个触发事件,在on_change事件触发后,my_say事件自动触发
通过创建一个单独的js文件event.js实现
(1)新建js文件夹及event.js文件
import Vue from 'vue'
export default new Vue;
(2)第一个组件
<template>
<section>
<div @click="pushMsg">push message</div>
<br>
</section>
</template>
<script>
import eventBus from "../utis/eventbus"
export default {
name:"Add",
data(){
return {
childNum:0
}
},
methods: {
pushMsg(){
// 通过事件总线发送消息
eventBus.$emit('pushMsg',this.childNum++)
}
},
}
</script>
(3)第二个组件
<template>
<section>
children1传过来的消息:{{msg}}
</section>
</template>
<script>
import eventBus from "../utis/eventbus"
export default {
name:"Son",
data(){
return {
msg:""
}
},
mounted() {
// 通过事件总线监听消息
eventBus.$on('pushMsg', (children1Msg) => {
this.msg = children1Msg
})
}
}
</script>
<style>
</style>
(3)父组件
<template>
<div id="app">
<Add></Add>
<Son></Son>
</div>
</template>
<script>
import Add from "./components/add.vue"
import Son from "./components/Son.vue"
export default {
name: 'App',
components: {
Add,
Son
},
data() {
return {
};
},
methods: {
},
}
</script>
<style>
</style>
最后,在总结一下兄弟组件传值的流程:
1、兄弟之间传递数据需要借助于事件总线,通过事件总线的方式传递数据
2、创建一个Vue的实例,让各个兄弟共用同一个事件机制。
3、通过 $emit 发射出事件,触发当前实例上的事件,并传一个参数
3、$on监听event事件后运行,通过一个事件触发bus.on(事件名,function(接收数据的参数){用该组件的数据接收传递过来的数据}),此时函数中的this已经发生了改变,可以使用箭头函数。
方法三:
其实传值还可以通过 vuex 和设置 Session Storage缓存的形式进行传递
const orderData = { 'orderId': 123, 'price': 88 }
// 存值
sessionStorage.setItem('缓存名称', JSON.stringify(orderData))
// 取值 (在另一个组件取出)
const dataB = JSON.parse(sessionStorage.getItem('缓存名称'))
4.路由间传值
i.使用问号传值
A页面跳转B页面时使用 this.$router.push(’/B?name=danseek’)
B页面可以使用 this.$route.query.name 来获取A页面传过来的值
上面要注意router和route的区别
ii.使用冒号传值
配置如下路由:
{
path: '/b/:name',
name: 'b',
component: () => import( '../views/B.vue')
},
在B页面可以通过 this.$route.params.name 来获取路由传入的name的值
iii.使用父子组件传值
由于router-view本身也是一个组件,所以我们也可以使用父子组件传值方式传值,然后在对应的子页面里加上props,因为type更新后没有刷新路由,所以不能直接在子页面的mounted钩子里直接获取最新type的值,而要使用watch
<router-view :type="type"></router-view>
// 子页面
......
props: ['type']
......
watch: {
type(){
// console.log("在这个方法可以时刻获取最新的数据:type=",this.type)
},
},
5.使用ref传值
通过$ref的能力,给子组件定义一个ID,父组件通过这个ID可以直接访问子组件里面的方法和属性
首先定义一个子组件Children.vue
<template>
<section>
传过来的消息:{{msg}}
</section>
</template>
<script>
export default {
name: "Children",
components: {},
data() {
return {
msg: '',
desc:'The use of ref'
}
},
methods:{
// 父组件可以调用这个方法传入msg
updateMsg(msg){
this.msg = msg
}
},
}
</script>
然后在父组件Parent.vue中引用Children.vue,并定义ref属性
<template>
<div class="parent">
<!-- 给子组件设置一个ID ref="children" -->
<Children ref="children"></Children>
<div @click="pushMsg">push message</div>
</div>
</template>
<script>
import Children from '../components/Children'
export default {
name: 'parent',
components: {
Children,
},
methods:{
pushMsg(){
// 通过这个ID可以访问子组件的方法
this.$refs.children.updateMsg('Have you received the clothes?')
// 也可以访问子组件的属性
console.log('children props:',this.$refs.children.desc)
}
},
}
</script>
6.使用依赖注入传给后代子孙曾孙
假设父组件有一个方法 getName(),需要把它提供给所有的后代
provide: function () {
return {
getName: this.getName()
}
}
provide 选项允许我们指定我们想要提供给后代组件的数据/方法
然后在任何后代组件里,我们都可以使用 inject
来给当前实例注入父组件的数据/方法:
inject: ['getName']
Parent.vue
<template>
<div class="parent">
<Children></Children>
</div>
</template>
<script>
import Children from '../components/Children'
export default {
name: 'Parent',
components: {
Children,
},
data() {
return {
name:'dan_seek'
}
},
provide: function () {
return {
getName: this.name
}
},
}
</script>
Children.vue
<template>
<section>
父组件传入的值:{{getName}}
</section>
</template>
<script>
export default {
name: "Children",
components: {},
data() {
return {
}
},
inject: ['getName'],
}
</script>
7.祖传孙$attrs
正常情况下需要借助父亲的props作为中间过渡,但是这样在父亲组件就会多了一些跟父组件业务无关的属性,耦合度高,借助$attrs可以简化些,而且祖跟孙都无需做修改。
8.孙传祖
9.$parent
10.sessionStorage传值
11.vex