跨级通信:vue.js官网提供的很好,解释的很好 ,值得去官网看
project()为组件后代提供数据
inject()注入上级提供数据
要实现如下图的页面,就是点击下方的按钮则页面显示响应的标题
根组件App.vue
<template>
<div>
<Navbar></Navbar>
<Tabbar></Tabbar>
</div>
</template>
<script>
import Navbar from './Navbar.vue';
import Tabbar from './Tabbar.vue'
export default {
data() {
return {
navtitle: 'app-首页'
}
},
provide() {
// 将asd提供给外面
return {
asd: this.navtitle,
// 将app共享出去
qwe: this
}
},
components: {
Navbar,
Tabbar,
}
}
</script>
<style scoped>
* {
margin: 0;
padding: 0;
}
ul {
list-style: none;
}
</style>
组件Navbar.vue
<template>
<div>
<button>返回</button>
<!-- <span>{{ asd }}</span> -->
<span>{{ qwe.navtitle }}</span>
<button>首页</button>
</div>
</template>
<script>
export default {
// 注入
inject: ['asd', 'qwe']
}
</script>
<style scoped>
div {
display: flex;
width: 100%;
justify-content: space-between;
height: 50px;
line-height: 50px;
background-color: #555;
}
</style>
组件Tabbar.vue
<template>
<ul>
<!-- <li v-for="data in datalist" :key="'data'">{{ data }}</li> -->
<TabbarItem v-for="data in datalist" :key="data" :item="data"></TabbarItem>
</ul>
</template>
<script>
import TabbarItem from './TabbarItem.vue';
export default {
data() {
return {
datalist: ['首页', '列表', '我的']
}
},
components: {
TabbarItem
}
}
</script>
<style>
ul {
display: flex;
position: fixed;
bottom: 0;
width: 100%;
height: 50px;
line-height: 50px;
}
li {
flex: 1;
text-align: center;
}
</style>
组件TabbarItem.vue(Tabbar.vue的子组件)
<template>
<li @click="handleClick">
{{ item }}
</li>
</template>
<script>
export default {
methods: {
handleClick() {
// 点击之后将item往上传,如何获取的呢
console.log(this.item);
console.log(this.asd);
this.qwe.navtitle = this.item
}
},
props: ['item'],
inject: ['asd', 'qwe']
}
</script>
后面还会继续改这个案例,这种写法不是很好,会增加耦合度
这个思路是App.vue通过provide()方法对外提供了navtitle数据,然后子组件都可以通过provide接受到这个navtitle数据并且能够使用,但是存在一个问题就是子组件想要修改收到的这个数据,发现这个数据不能响应式修改,然后就想到了使用App.vue直接提供app这个对象,那不就可以解决这个问题啦,然后就有上面的页面
优点就是跨级访问变得简洁便利了,省去中间传递的麻烦
在vue2选项式中缺点就是app这个实例随意的跨级给任何孩子,任何孩子都可以随意去修改状态,数据变的不可控,增加耦合度
在vue3中provide可以提供响应式,更加好用
未完待续...后面还会修改这个案例